What is the relation between the classes R, RE coRE, as opposed to P,NP,coNP - turing-machines

I am trying to understand the relation between these classes of languages.
Can someone do some order in my way of thinking of this? For example, if i take the language HAMPATH = {: G has a hamiltonion path}. I know this is in NP and also NP hard. Does this teach me anything about being in R, RE coRE? is there any connection between them?

All problems in P, NP, and co-NP are decidable, so all of these classes are strict subsets of R. It's known that R is a strict subset of both RE and co-RE and, furthermore, that R = RE ∩ co-RE.
There's a nice intuitive connection between these classes. The definitions of R, RE, and co-RE can essentially be described as
R languages are languages that can be decided.
RE languages are languages that have verifiers.
co-RE languages are languages whose complements are in RE.
The definitions of P, NP, and co-NP are
P languages are languages that can be decided in polynomial time.
NP languages are languages that have verifiers that run in polynomial time.
co-NP languages are languages whose complements are in NP.
In a sense, you can go from one class of languages to the other by adding or removing a polynomial-time restriction. (This also helps explain the containments).

Related

How does one implement hash tables in a functional language?

Is there any way to implement hash tables efficiently in a purely functional language? It seems like any change to the hash table would require creating a copy of the original hash table. I must be missing something. Hash tables are pretty darn important data structures, and a programming language would be limited without them.
Is there any way to implement hash tables efficiently in a purely functional language?
Hash tables are a concrete implementation of the abstract "dictionary" or "associative array" data structure. So I think you really want to ask about the efficiency of purely functional dictionaries compared to imperative hash tables.
It seems like any change to the hash table would require creating a copy of the original hash table.
Yes, hash tables are inherently imperative and there is no direct purely functional equivalent. Perhaps the most similar purely functional dictionary type is the hash trie but they are significantly slower than hash tables due to allocations and indirections.
I must be missing something. Hash tables are pretty darn important data structures, and a programming language would be limited without them.
Dictionaries are a very important data structure (although its worth noting that they were rare in the mainstream until Perl made them popular in the 1990s, so people coded stuff for decades without benefit of dictionaries). I agree that hash tables are also important because they are often by far the most efficient dictionaries.
There are many purely functional dictionaries:
Balanced trees (red-black, AVL, weight-balanced, finger trees etc.), e.g. Map in OCaml and F# and Data.Map in Haskell.
Hash tries, e.g. PersistentHashMap in Clojure.
But these purely functional dictionaries are all much slower than a decent hash table (e.g. the .NET Dictionary).
Beware Haskell benchmarks comparing hash tables to purely functional dictionaries claiming that purely functional dictionaries are competitively performant. The correct conclusion is that Haskell's hash tables are so inefficient that they are almost as slow as purely functional dictionaries. If you compare with .NET, for example, you find that a .NET Dictionary can be 26Γ— faster than Haskell's hash table!
I think to really conclude what you're trying to conclude about Haskell's performance you would need to test more operations, use a non-ridiculous key-type (doubles as keys, what?), not use -N8 for no reason, and compare to a 3rd language that also boxes its parametric types, like Java (as Java has acceptable performance in most cases), to see if its a common problem of boxing or some more serious fault of the GHC runtime. These benchmarks are along these lines (and ~2x as fast as the current hashtable implementation).
This is exactly the kind of misinformation I was referring to. Pay no attention to Haskell's hash tables in this context, just look at the performance of the fastest hash tables (i.e. not Haskell) and the fastest purely functional dictionaries.
Hash tables can be implemented with something like the ST monad in Haskell, which basically wraps IO actions in a purely functional interface. It does so by forcing the IO actions to be performed sequentially, so it maintains referential transparency: you can't access the old "version" of the hash-table.
See: hackage.haskell.org/package/hashtables
The existing answers all have good points to share, and I thought I would just add one more piece of data to the equation: comparing performance of a few different associative data structures.
The test consists of sequentially inserting then looking up and adding the elements of the array. This test isn't incredibly rigorous, and it shouldn't be taken as such, it just an indication of what to expect.
First in Java using HashMap the unsynchronized Map implementation:
import java.util.Map;
import java.util.HashMap;
class HashTest {
public static void main (String[] args)
{
Map <Integer, Integer> map = new HashMap<Integer, Integer> ();
int n = Integer.parseInt (args [0]);
for (int i = 0; i < n; i++)
{
map.put (i, i);
}
int sum = 0;
for (int i = 0; i < n; i++)
{
sum += map.get (i);
}
System.out.println ("" + sum);
}
}
Then a Haskell implementation using the recent hashtable work done by Gregory Collins (its in the hashtables package). This can be both pure (through the ST monad) or impure through IO, I'm using the IO version here:
{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}
module Main where
import Control.Monad
import qualified Data.HashTable.IO as HashTable
import System.Environment
main :: IO ()
main = do
n <- read `fmap` head `fmap` getArgs
ht :: HashTable.BasicHashTable Int Int <- HashTable.new
mapM_ (\v -> HashTable.insert ht v v) [0 .. n - 1]
x <- foldM (\ !s i -> HashTable.lookup ht i >>=
maybe undefined (return . (s +)))
(0 :: Int) [0 .. n - 1]
print x
Lastly, one using the immutable HashMap implementation from hackage (from the hashmap package):
module Main where
import Data.List (foldl')
import qualified Data.HashMap as HashMap
import System.Environment
main :: IO ()
main = do
n <- read `fmap` head `fmap` getArgs
let
hashmap =
foldl' (\ht v -> HashMap.insert v v ht)
HashMap.empty [0 :: Int .. n - 1]
let x = foldl' (\ s i -> hashmap HashMap.! i + s) 0 [0 .. n - 1]
print x
Examining the performance for n=10,000,000 , I find the total running time is the following:
Java HashMap -- 24.387s
Haskell HashTable -- 7.705s, 41% time in GC (
Haskell HashMap -- 9.368s, 62% time in GC
Knocking it down to n=1,000,000, we get:
Java HashMap -- 0.700s
Haskell HashTable -- 0.723s
Haskell HashMap -- 0.789s
This is interesting for two reasons:
The performance is generally pretty close (except where Java diverges above 1M entries)
A huge amount of time is spent in collection! (killing Java in the case of n=10,0000,000).
This would seem to indicate that in languages like Haskell and Java which have boxed the map's keys see a big hit from this boxing. Languages that either do not need, or can unbox the keys and values would likely see couple times more performance.
Clearly these implementations are not the fastest, but I would say that using Java as a baseline, they are at least acceptable/usable for many purposes (though perhaps someone more familiar with Java wisdom could say whether HashMap is considered reasonable).
I would note that the Haskell HashMap takes up a lot of space compared to the HashTable.
The Haskell programs were compiled with GHC 7.0.3 and -O2 -threaded, and run with only the +RTS -s flag for runtime GC statistics. Java was compiled with OpenJDK 1.7.

Proving a language is in RE/R/coRE

Lets say we have a function for a Turing Machine like this one:
𝑓(𝑀) = { 1, for any 𝑀 where 𝑀(𝑀) halts only if w is a palindrome of even length
0, otherwise
How can one prove that it belongs (or not) to RE, R, coRE.
I mean, I know we can use a turing reduction using the f-halt to prove that it is not belonging to R. But what about RE/coRE?
A language is RE if we can halt-accept for any string in the language. A language is coRE if we can halt-reject for any string not in the language. R is the intersection of RE and coRE; a language is R if we can halt-accept on strings in the language and halt-reject on strings not in the language.
You already know that the language isn't R. This can also be seen by Rice's theorem: halting only on palindromes of even length is a semantic property of the accepted language (subset of EPAL), so the inclusion problem isn't decidable. This tells you that the language cannot be both RE and coRE, though it might be neither.
Given a machine M, can we determine that it does only accept strings which are even-length palindromes? This seems unlikely. We would need a way to be sure that all strings - maybe infinitely many - are even-length palindromes. We can't just find a counterexample and be done.
Given a machine M, can we determine that it doesn't only accept strings which are even-length palindromes? We sure can! We can interleave executions of copies of this machine such that arbitrarily many possible input strings get arbitrarily much computing time; if M accepts any particular string, we can eventually find out, and if it accepts one that isn't an even-length palindrome, we can eventually tell.
So, this language:
is coRE
is not RE
is not R

How to throw an exception on `float==float` operation? [closed]

Imagine that an inexperienced programmer tries to compare 2 floats for equivalence:
a = 0.01
b = 0.1 ** 2
print(a == b)
Is there any language that would throw an exception on such foolishness? Or a way to override the default behaviour in python and/or javascript?
If not, what is the reason behind language design decision to allow the operation?
EDIT: Looks like I've been accused of suggesting to make comparisons of floats impossible. I have nothing against a < b or float_eq(a, b). It's just that most people have very different intuition about what ==, !=, >= and <= operators are supposed to do from what they actually do with float numbers. There are various precedents in language design to prevent some of the dumber mistakes people tend to make, like disallowing if(a=b) in python or use strict in perl.
I don't know of a mainstream language that treats the use of '==' on floating point as an error, or that allows you to overload '==' for primitive types.
But I don't think it would be a good idea either, because '==' can be used safely on floating point in limited situations ... if you know what you are doing.
A better approach (if you want to protect programmers against naive mistakes with '==') would be to implement this as a rule in your language's preferred static code checker; e.g. the analogue to Lint (for C) and PMD or FindBugs (for Java).
Why throw an exception for a construct, float == float, where everything is static? Unless you were planning to accept if (false && float == float) …, you might as well reject this construct statically.
In fact, why have float == float in the language at all? There are perfectly good languages without floating-point. Programmers that are so inexperienced as to foolishly try to use floating-point computations would be better off using a programming language that does not have them. I would personally recommend Ook.
I should point out that it is possible to use floating-point intelligently, just like most other constructs found in programming languages can be used intelligently. The CRlibm library contains several beautiful patterns of subtle floating-point computations. It helps when the programming language gives the programmer strong hypotheses on the way source code will be translated to the IEEE 754 hardware instructions that nearly all processors have had for years. The CRlibm library is written for a C99 compiler that implements IEEE 754 without excess precision. You could implement the same library in Java, but not conveniently in C#, for instance.
In conclusion, floating-point equality is as useful as other floating-point operations, and it is mathematically exact, unlike most of them. You might as well not use floating-point at all, which you can do in any language, and in particular in C#. If you are not sure you can refrain from using floating-point computation if it is available in the programming language, program in Ook.
0.01 == 0.1 ** 2 may or may not work (I haven't checked), but 0.25 == 0.5 ** 2 is absolutely guaranteed to work, and so is 0.1 ** 2 == 0.1 ** 2. It's important to understand why you can't necessarily count on floating point numbers to be equal where the equations say they should be equal, but in certain circumstances it is perfectly reasonable, and quite useful, to count on floating point equality. A language which disallowed the operation would be less powerful than one which did not.

Define natural numbers in functional languages like Ada subtypes

In Ada to define natural numbers you can write this:
subtype Natural is Integer range 0 .. Integer'Last;
This is type-safe and it is checked at compile-time. It is simple (one-line of code) and efficient (it does not use recursion to define natural numbers as many functional languages do). Is there any functional language that can provide similar functionality?
Thanks
This is type-safe and it is checked at compile-time.
As you already pointed out in the comments to your question, it is not checked at compile time. Neither is equivalent functionality in Modula-2 or any other production-ready, general-purpose programming language.
The ability to check constraints like this at compile time is something that requires dependent types, refinement types or similar constructs. You can find those kinds of features in theorem provers like Coq or Agda or in experimental/academic languages like ATS or Liquid Haskell.
Now of those languages I mentioned Coq and Agda define their Nat types recursively, so that's not what you want, and ATS is an imperative language. So that leaves Liquid Haskell (plus languages that I didn't mention, of course). Liquid Haskell is Haskell with extra type annotations, so it's definitely a functional language. In Liquid Haskell you can define a MyNat (a type named Nat is already defined in the standard library) type like this:
{-# type MyNat = {n:Integer | n >= 0} #-}
And then use it like this:
{-# fac :: MyNat -> MyNat #-}
fac :: Integer -> Integer
fac 0 = 1
fac n = n * fac (n-1)
If you then try to call fac with a negative number as the argument, you'll get a compilation error. You will also get a compilation error if you call it with user input as the argument unless you specifically check that the input was non-negative. You would also get a compilation error if you removed the fac 0 = 1 line because now n on the next line could be 0, making n-1 negative when you call fac (n-1), so the compiler would reject that.
It should be noted that even with state-of-the-art type inference techniques non-trivial programs in languages like this will end up having quite complicated type signatures and you'll spend a lot of time and effort chasing type errors through an increasingly complex jungle of type signatures having only incomprehensible type errors to guide you. So there's a price for the safety that features like these offer you. It should also be pointed out that, in a Turing complete language, you will occasionally have to write runtime checks for cases that you know can't happen as the compiler can't prove everything even when you think it should.
Typed Racket, a typed dialect of Racket, has a rich set of numeric subtypes and it knows about a fair number of closure properties (eg, the sum of two nonnegative numbers is nonnegative, the sum of two exact integers is an exact integer, etc). Here's a simple example:
#lang typed/racket
(: f : (Nonnegative-Integer Nonnegative-Integer -> Positive-Integer))
(define (f x y)
(+ x y 1))
Type checking is done statically, but of course the typechecker is not able to prove every true fact about numeric subtypes. For example, the following function in fact only returns values of type Nonnegative-Integer, but the type rules for subtraction only allow TR to conclude the result type of Integer.
> (lambda: ([x : Nonnegative-Integer] [y : Nonnegative-Integer])
(- x (- x y)))
- : (Nonnegative-Integer Nonnegative-Integer -> Integer)
#<procedure>
The Typed Racket approach to numbers is described in Typing the Numeric Tower by St-Amour et al (appeared at PADL 2012). There's usually a link to the paper here, but the link seems to be broken at the moment. Google has a cached rendering of the PDF as HTML, if you search for the title.

Why is β€œInt ^ Int” in Scala not exponentiation? (What is it?)

^ was always supposed to mean exponentiation. But it doesnt behave that way. What does it actually mean, and are there any member functions of Int that do exponentiation (other than math.pow)?
And why was it defined that way? It gets an operator precedence lower than arithemetic operations, when all other languages give it the highest precedence.
It's bitwise exclusive or. You've probably never developed in C, C++, or Java, or...
It's inherited from them. I don't know how one would define what it's "supposed" to be, but there's certainly a lot of code written with this meaning.
Int (and RichInt) don't have an exponentiation operator.
As far as precedence goes, it's in the middle of the other logical operators, which is where it belongs given its actual meaning (as opposed to exponentiation).
If you really wanted to override the meaning of "^" within a restricted scope (something I do not recommend), I think you could do so using implicit parameters, thereby getting the high precedence you want. Or, more sanely, I think you could define a "to_the" or "**" operator the same way, getting the same high precedence.
Well, "all other languages" is a very strong statement.
'^' in Scala comes from Java (where it came from the general vicinity of the C language), and means bitwise XOR.
And it's used as XOR in various other languages as well, eg. in Python.
Many languages have some kind of exponentiation operator: R, Matlab, BASIC, LaTeX, and UNIX's bc use '3^2', Ada, COBOL, PL/I, Python and Fortran use '3**2'.
I've seen it claimed that exponentiation is relatively rare, but I'll say in many years of programming I've never needed an XOR and it's been many years since I've needed any kind of bit operation at all -- probably back to the days when they measured RAM in KB. On the other hand, I do exponentiation quite often.
Seems to me that if I were going to use Scala as my R, I might consider something like:
implicit class FixPow(x: Double) { def ~^(p: Double): Double = Math.pow(x, p) }
which is a bit ugly, but does have a higher precedence than '*', which is what's needed. So '3 * 2 ~^ 3' evaluates to 24, as expected.
C's support for a full set of bit operations comes from the fact that UNIX was written in C. It essentially codified assembly language patterns.

Resources