Game of Life Ocaml with Matrix - arrays

I have generated a matrix for my Game of Life, and I'm trying to make it so that it loops through and continuously prints out the next generation, I am using a code I found online, and it doesn't seem to work. Here is my code
let generation = ref 1
let get g x y =
try g.(x).(y)
with _ -> 0
;;
let neighbourhood g x y =
(get g (x-1) (y-1)) +
(get g (x-1) (y )) +
(get g (x-1) (y+1)) +
(get g (x ) (y-1)) +
(get g (x ) (y+1)) +
(get g (x+1) (y-1)) +
(get g (x+1) (y )) +
(get g (x+1) (y+1))
let next_cell g x y =
let n = neighbourhood g x y in
match g.(x).(y), n with
| 1, 0 | 1, 1 -> 0 (* lonely *)
| 1, 4 | 1, 5 | 1, 6 | 1, 7 | 1, 8 -> 0 (* overcrowded *)
| 1, 2 | 1, 3 -> 1 (* lives *)
| 0, 3 -> 1 (* get birth *)
| _ -> 0
let copy g = Array.map Array.copy g
let rec next g =
let width = Array.length g
and height = Array.length g.(0)
and new_g = copy g in
for x = 0 to pred width do
for y = 0 to pred height do
new_g.(x).(y) <- (next_cell g x y)
done
done;
next new_g
let print g =
let width = Array.length g
and height = Array.length g.(0) in
for x = 0 to pred width do
for y = 0 to pred height do
if g.(x).(y) = 0
then print_char '.'
else print_char 'o'
done;
print_newline()
done
;;
print_string "Width ";
let num = read_int () in
print_string "Height";
let num2 = read_int () in
while !generation < 100 do
let myArray = Array.init num (fun _ -> Array.init num2 (fun _ -> Random.int 2)) in
print_string "Generation: "; print_int !generation; print_string "\n";
print (next myArray);
generation := !generation +1;
print_newline();
done;;
It only prints out the initial one and the generation after that rather than a new one. Since the parameters is the original array, however, when I put print (next new_g) it gives me an unbound value, is there a way I can continuously print out the subsequent generations?Shouldn't it overwrite the existing new_g when I do that?

Looking just at the main while loop, it allocates and initializes a random array each time around the loop. It doesn't seem like this could be right.
I also don't see how the function next could work, as it never returns. Its last action is to call itself again, unconditionally.
Update
If you change the last line of next to this:
new_g
it returns the next generation each time you call it.
Here's a way to drive the code in a functional (rather than imperative) style:
let rec generation n array =
if n < 100 then
begin
(* Print the array *);
generation (n + 1) (next array)
end
The outermost code might look like this:
let myArray =
Array.init num
(fun _ -> Array.init num2 (fun _ -> Random.int 2))
in
generation 0 myArray

Related

Creating an array with a function using index and array?

I am wanting to create an array of the Fibonacci numbers using haskell, but using a this more efficient algorithm
F(2K) = F(K)[2F(K-1)-F(K)]
F(2K+1) = F(K+1)^2 + F(K)^2
I know the function works and I can pass through the index or the array but not both and I can't figure out why
fastFibo :: Array Int Int -> Int -> Int
fastFibo a 0 = 0
fastFibo a 1 = 1
fastFibo a 2 = 1
fastFibo a x = do
if ((mod x 2) == 0)
then do
let y = div x 2
(a!y) * (2 * (a!(y+1)) - (a!y))
else do
let y = div (x-1) 2
(a!y)^2 + (a!(y+1))^2
fibos n = a where a = array (0,n) ([(0, 0), (1, 1), (2,1)] ++ [(i, fastFibo(a i)) | i <- [2..n]])
The error I get is
• Couldn't match expected type ‘i1 -> Array Int Int’
with actual type ‘Array i1 (Int -> Int)’
• Possible cause: ‘array’ is applied to too many arguments
In the expression:
array
(0, n)
([(0, 0), (1, 1), (2, 1)] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
In an equation for ‘a’:
a = array
(0, n)
([(0, 0), (1, 1), (2, 1)] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
In an equation for ‘fibos’:
fibos n
= a
where
a = array
(0, n) ([(0, 0), ....] ++ [(i, fastFibo (a i)) | i <- [2 .. n]])
• Relevant bindings include
a :: i1 -> Array Int Int
(bound at /mnt/data/Documents/Programming/Haskell/Arrays/Arrays.hs:20:19)
|
20 | fibos n = a where a = array (0,n) ([(0, 0), (1, 1), (2,1)] ++ [(i, fastFibo(a i)) | i <- [2..n]])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Using a less fast algorithm that still operates on an array, you could do:
import Data.Array
fib :: Int -> Int
fib n = arr ! n
where
arr :: Array Int Int
arr = listArray (1, n) $
0 : 1 : [ (arr ! (i-1)) + (arr ! (i-2)) | i <- [3..n] ]
If you were to transform this to use your faster algorithm, it'd be something like:
import Data.Array
fib :: Int -> Int
fib n = arr ! n
where
arr :: Array Int Int
arr = listArray (1, n) $
0 : 1 : 1 : map fib' [4..n]
fib' :: Int -> Int
fib' k
| even k = ...
| otherwise = ...
I figured listArray was sufficient here. It's pretty close to array which you use.
See the documentation on array construction for the difference.

Using unsafePerformIO in a guard condition

I have a function like this:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr
| nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && CONDITION = XXX
| otherwise = YYY
The CONDITION must check that that element (1,1) of the array arr is different from 0. But to get this element, one must do
element <- readArray arr (1,1)
I don't see how to do. Except with unsafePerformIO. Is it safe to use it here ? I mean:
| k == 0 && unsafePerformIO (readArray arr (1,1)) /= 0 = XXX
Otherwise, how could I do ?
Let's make a simplified version of your question.
Let's say we want to make the following function. It tells us whether or not both of the Int values are equal to 0. Problem is, it contains an IO. Your current method is this:
-- THIS IS BAD CODE! This could easily cause unexpected behaviour.
areBothZero :: Int -> IO Int -> IO Bool
areBothZero a b
| a == 0 && unsafePerformIO b == 0 = return True
| otherwise = return False
This shows a misunderstanding of monads. In Haskell, unsafePerformIO as a general rule shouldn't be used, unless you want to achieve a certain effect that pure computation cannot achieve. However, this kind of situation is perfectly achievable using the monad operations, which are, unlike unsafePerformIO, perfectly safe.
This is how we achieve this. Firsly, write the logic outside the context of IO:
areBothZeroLogic :: Int -> Int -> Bool
areBothZeroLogic a b
| a == 0 && b == 0 = True
| otherwise = False
Then, we pipe that up to the IO logic we want:
areBothZeroIO :: Int -> IO Int -> IO Bool
areBothZeroIO a mb = do
b <- mb -- Use do-notation to work with the value 'inside' the IO:
return $ areBothZeroLogic a b
Immediately, this separates IO logic from pure logic. This is a fundamental design principle in Haskell that you should always try to follow.
Now, onto your problem.
Your problem is much more messy and has several other issues, which suggests to me that you haven't considered how best to split the problem up into smaller peices. However, a better solution may look something like this, maybe with better names:
-- Look here! vvvvvv vvvvvv
jacPure :: Int -> Int -> [Int] -> [Int] -> Double -> Double
jacPure m k mu nu arrVal
| nu!!0 == 0 = 1
| length nu > m && nu!!m > 0 = 0
| m == 1 = x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && arrVal /= 0 = XXX
| otherwise = YYY
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr = do
arrVal <- readArray arr (1,1) -- Use do-notation to work with the value 'inside' the IO:
return $ jacPure m k mu nu arrVal
You should see immediately why this is much better. When implementing logic, who cares what's going on in the IO domain? Including an IO in what should be pure logic is like telling an author about the acidity of the paper their book will be printed on—it isn't relevant to what their job is. Always separate logic and IO!
There are of course other ways of doing this, and some could very well be better than the way I have suggested. However, it is not possible to know with the code you have provided which the best path would be. You should aim to learn more about monads and get better at using them, so you can make this judgement on your own.
I suspect this question is borne from a lack of understanding of Monads and monadic operations. If you are a beginner, I recommend reading the relevant LYAH chapter, which I found helpful as a beginner too.
One option is to combine the last two cases:
jac m k mu nu arr
...
| k == 0 = do
element <- readArray arr (1,1)
case element of
0 -> YYY
_ -> XXX
| otherwise -> YYY
Suppose we have
areBothZero :: Int -> IOArray Int Int -> IO Bool
areBothZero a b
| a == 0 && unsafePerformIO (readArray b 0) == 0 = return True
| otherwise = return False
I think it's worth thinking about what can go wrong. Suppose I write
do
x <- areBothZero a b
-- Change the value in b[0]
y <- areBothZero a b
Now there are two identical function calls, so the compiler is perfectly free to rewrite this:
do
let m = areBothZero a b
x <- m
-- change b
y <- m
The first time we run m, we perform the IO, reading b and getting an action return True or return False. We run that action and bind the result to x. The next time, we already have an action, so we run it, producing the same result. Any change to b is ignored.
This is only one of the ways things can go wrong with unsafePerformIO, so watch out!
I think there are one and a half ways it's reasonable to use unsafePerformIO or (in some cases) unsafeDupablePerformIO routinely. The entirely reasonable one is to wrap an "essentially pure" FFI call that just performs a mathematical calculation in another language. The less reasonable one is to create a global IORef or (more often) MVar. I think this is less reasonable because global variables have a certain tendency to turn out not to be as global as you thought once a year or two has passed. Most other uses of these unsafe IO operations require very careful thought to get right These tend to be in libraries like monad-par and reflex that introduce whole new styles of computation to Haskell. They also tend to be subtly buggy, sometimes for years, until someone figures out just what needs to happen to make them right. (Not to toot my own horn too much, but I think I'm probably one of the top handful of people in the world at reasoning about unsafe IO, and I very much prefer to avoid it when possible. This stuff has tripped up some of the best Haskell programmers and most important GHC developers.)
I've found a solution. I pass the value of the array element in addition.
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> Double -> IO Double
jac m k mu nu arr elt
| nu!!0 == 0 || m == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && elt /= 0 = XXX
| otherwise = do
e <- readArray arr (1, 1)
jck <- jac (m-1) 0 nu nu arr e
......
Maybe my question was not precise enough...
Not terribly elegant, but should do:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr
| nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| otherwise = do
v <- readArray arr (1,1)
case () of
_ | k == 0 && v /= 0 -> XXX
| otherwise -> YYY
Alternatively, read from the array at the very beginning:
jac :: Int -> Int -> [Int] -> [Int] -> IOArray (Int,Int) Double -> IO Double
jac m k mu nu arr = do
v <- readArray arr (1,1)
case () of
_ | nu!!0 == 0 = return 1
| length nu > m && nu!!m > 0 = return 0
| m == 1 = return $ x!!0^(nu!!0) * theproduct (nu!!0)
| k == 0 && v /= 0 -> XXX
| otherwise -> YYY

OCaml - Find the smallest missing number in a sorted list

I've been trying to implement a function in OCaml that returns the smallest missing number (greater than 0) in a sorted list.
Here is what I've done
let getMissingNumber l =
let rec find min = function
| [] -> min
| t :: [] -> t + 1
| t1 :: t2 :: r -> if t2 - t1 > 1 then t1 + 1 else find min (t2 :: r)
in find 1 l;;
Here are the results:
# getMissingNumber [1; 4; 5];;
- : int = 2
# getMissingNumber [1; 2; 5];;
- : int = 3
# getMissingNumber [1; 2; 3];;
- : int = 4
# getMissingNumber [3; 4; 5];;
- : int = 6
All the results are correct but the last one. Any suggestions?
The problem is that if list contains more than one element, this function will never return 1, just because of | t :: [] -> t + 1 (if t > 0).
So we may replace | t :: [] -> t + 1 by | t :: [] -> min, but in this case there will be a problem with all lists of the form [1; 2; 3; ...; n], because in the | t1 :: t2 :: r branch we don't change min, so we will end up by returning 1 (even if correct response is n+1).
So we need to "update" min, but what's interesting is that if we replace find min (t2 :: r) by find (t2 + 1) (t2 :: r), we will return to your original function.
In fact this function search smallest missing number greater than smallest presented number. The main problem is that you distinguish [t] and t1::t2::r for no good reason.
let getMissingNumber l =
let rec find min = function
| [] -> min
| t::r ->
if t > min then min
else find (t + 1) r
in find 1 l
If the input list may start with values smaller than one, then you also need to skip over these.
let getMissingNumber l =
let rec find min = function
| [] -> min
| h :: t when min < t -> min
| h :: t when min = t -> find (min+1) t
| _ :: t -> find min t
in find 1 l

MATLAB two different arrays for the same variable

So, I got a strange problem.
Below is my code, it is a simple Euler method for integrating a Linear system of ODE's.
function [V, h, n, b, z] = hodgkin_huxley_CA1(t, Iapp, t_app)
%function based on the CA1 pyramidal neuron model:
h = zeros(length(t));
n = zeros(length(t));
b = zeros(length(t));
z = zeros(length(t));
V = zeros(length(t));
% Initial conditions
h(1) = 0.9771;
n(1) = 0.0259;
b(1) = 0.1787;
z(1) = 8.0222e-04;
V(1) = -71.2856;
% Euler method
delta_t = t(2) - t(1);
for i=1:(length(t)-1)
h(i+1) = h(i) + delta_t*feval(#h_prime,V(i),h(i));
n(i+1) = n(i) + delta_t*feval(#n_prime,V(i),n(i));
b(i+1) = b(i) + delta_t*feval(#b_prime,V(i),b(i));
z(i+1) = z(i) + delta_t*feval(#z_prime,V(i),z(i));
minf = m_inf(V(i));
pinf = p_inf(V(i));
ainf = a_inf(V(i));
if (t(i) >= t_app(1) && t(i) <= t_app(2))
I = Iapp;
else I = 0;
end;
V(i+1) = V(i) + delta_t*feval(#V_prime,V(i),h(i),n(i),b(i),z(i),minf,pinf,ainf,I);
end;
So, this function returns me 5 arrays, V,h,n,b and z. The problem is that if I use V(1), V(2), V(3), ..., I get the expected result. But when I tell matlab to print the whole array, I receive all values as 0.
So, if I plot this array, I will get 2 curves: one that is the right one, and one that is zero.
Note that this also happens to all the other variables h,n,b and z.
Anyone knows what may be happening?
Your outputs are meant to be vectors, however you are initializing them as square matrices.
You can simply replace:
h = zeros(length(t));
n = zeros(length(t));
b = zeros(length(t));
z = zeros(length(t));
V = zeros(length(t));
With
h = zeros(length(t),1);
n = zeros(length(t),1);
b = zeros(length(t),1);
z = zeros(length(t),1);
V = zeros(length(t),1);
The zeros function, with 1 input, creates a 2D square matrix of that dimension. With two or more inputs, it interprets the inputs as specification for all dimensions. For example:
>> x = zeros(3)
x =
0 0 0
0 0 0
0 0 0
>> x = zeros(3,1)
x =
0
0
0

Printing a 2d array in haskell

I'm messing around with printing a random 2d array of Ints, in this simple image format (PPM)
0 1 0 0 1
1 0 0 1 0
0 1 1 0 0
0 1 1 1 0
0 0 0 1 0
Below is my code, which works, but seems like way too much code for such a simple operation. Is there a better way to do this?
import System.Random
import Data.Array.IArray
main = do
g <- newStdGen
let img = listArray ((0,0),(5,5)) ( myRands g ) :: Array (Int,Int) Int
putStrLn $ printArray img
myRands :: RandomGen g => g -> [Int]
myRands g = randomRs (0,1) g
make2dRange :: Int -> Int -> Int -> Int -> [(Int,Int)]
make2dRange x1 y1 x2 y2 = range ((x1,y1),(x2,y2))
printArray :: ( Array (Int,Int) Int ) -> String
printArray arr = unlines rows
where rows = map (unwords . map (show . (!) arr)) rowIndices
rowIndices = map ( \y -> make2dRange 0 y 5 y ) [0..5]
Other than the obvious, of course (array dimensions are hardcoded, for example)
I would use list comprehensions to manipulate the indices.
printArray arr =
unlines [unwords [show (arr ! (x, y)) | x <- [0..5]] | y <- [0..5]]
per: http://lambda.haskell.org/platform/doc/current/packages/split-0.2.2/doc/html/Data-List-Split.html#v%3achunksOf
chunksOf :: Int -> [e] -> [[e]]
chunksOf n splits a list into length-n pieces. The last piece will be shorter if n does not evenly divide the length of the list. If n <= 0, chunksOf n l returns an infinite list of empty lists.
using chunksOf my implementation would be..
printArray arr = mapM_ (putStrLn . unwords) $ map (map show) $ chunksOf 5 arr
usage:
Prelude System.Random Data.List Data.List.Split> printArray [0..25]
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25

Resources