I want to get the sum of function f(i) values when i is equal from a to b
= f(a)+f(a+1)+...+f(b-1)+f(b)
So I wrote code like this.
let rec sigma : (int -> int) -> int -> int -> int
= fun f a b ->
if a=b then f a
else f b + sigma f a b-1 ;;
but result is that there is stack overflow during evaluation. Is there a infinite loop? and why?
sigma f a b-1 is parsed as (sigma f a b) - 1 instead of your intention, sigma f a (b-1). Since sigma f a b calls sigma f a b recursively in your code, it never stops.
The best practice is to put white spaces around binary operators like sigma f a b - 1 so that you would not misread what you write.
Related
I have this question that is messing me up because I am not getting that where should I start, which terms should I pick at the beginning? Because this confusing expression does not even let me take the common as it makes no sense. Also, it does not even let me remove compliments (using the Laws) as it also does not make any sense. Please help me in this, at least just guide me what should I do? From where should I start? I would be really grateful.
The Explanation of Symbols I used to write the expression:
! : NOT Gate
+ : OR Gate
. (dot) : AND Gate
Boolean Expression:
A.!B.E + !(B.C).D.!E + !(C.D).E+!A.D.!E + A.!(C.D).E + A.E + A.B.!E + !(A.C) + B.C.!D
I have used an online expression simplifier and that gave me the following answer:
!A + B + !C + D + E
But how the above long expression has been simplified in this short one? I know the Laws and Properties but I am not getting that how should I start simplifying the long one? Which terms should I see first? Kindly anyone please help me.
(This is a direct answer to your comment, and a side-ways answer to your main question. In short, use a different method to get the desired simplified expression.)
You have a complicated expression, but one that uses only 5 logical variables. In this problem it would be much easier to build a truth table, which would have just 2^5 = 32 rows. You could look at the results and use those to build a simplified, equivalent expression. This does not use "the laws and properties" that your original question requires, but it is a standard technique to simplify Boolean expressions.
You should have learned how to build a truth table in just about any Discrete Mathematics class. In short, you make a table where each element in each row is a T for True or F for False. The rows contain all possible combinations of Ts and Fs. For 5 variables this would use 2^5 = 32 rows. For each row, you assign the first value to A, the second to B, etc. You then evaluate the expression for those values and write the result at the end of the line.
This can be done by hand, but your expression is complicated enough that we could avoid that. Here is a Python 3 script that prints the desired table. Note that Python has the product() function which simplifies getting all possible combinations of Ts and Fs. This script used B[] to convert a Boolean value to a single character T or F.
from itertools import product
"""Make a truth table for the Boolean expression
A.!B.E + !(B.C).D.!E + !(C.D).E+!A.D.!E + A.!(C.D).E + A.E + A.B.!E + !(A.C) + B.C.!D
"""
B = ('F', 'T')
print('A B C D E : Result')
print('- - - - - : ------')
for a, b, c, d, e in product((True, False), repeat=5):
print(B[a], B[b], B[c], B[d], B[e], end=' : ')
print(B[
(a and not b and e)
or (not (b and c) and d and not e)
or (not (c and d) and e)
or (not a and d and not e)
or (a and not (c and d) and e)
or (a and e)
or (a and b and not e)
or (not (a and c))
or (b and c and not d)
])
Here are the results:
A B C D E : Result
- - - - - : ------
T T T T T : T
T T T T F : T
T T T F T : T
T T T F F : T
T T F T T : T
T T F T F : T
T T F F T : T
T T F F F : T
T F T T T : T
T F T T F : T
T F T F T : T
T F T F F : F
T F F T T : T
T F F T F : T
T F F F T : T
T F F F F : T
F T T T T : T
F T T T F : T
F T T F T : T
F T T F F : T
F T F T T : T
F T F T F : T
F T F F T : T
F T F F F : T
F F T T T : T
F F T T F : T
F F T F T : T
F F T F F : T
F F F T T : T
F F F T F : T
F F F F T : T
F F F F F : T
We see that the result is always T except for the single line T F T F F. This means your expression is true unless A is True, B is False, C is True, and D and E are False. So we can simplify your expression (using your notation) to
!(A.!B.C.!D.!E)
A simple use of DeMorgan's laws changes this to normal form:
!A + B + !C + D + E
which is what you wanted.
Is it possible to have nested if without else statements. I wrote the following useless program to demonstrate nested ifs. How do I fix this so it's correct in terms of syntax. lines 5 and 6 gives errors.
let rec move_helper b sz r = match b with
[] -> r
|(h :: t) ->
if h = 0 then
if h - 1 = sz then h - 1 ::r
if h + 1 = sz then h + 1 ::r
else move_helper t sz r
;;
let move_pos b =
move_helper b 3 r
;;
let g = move_pos [0;8;7;6;5;4;3;2;1]
You can't have if without else unless the result of the expression is of type unit. This isn't the case for your code, so it's not possible.
Here's an example where the result is unit:
let f x =
if x land 1 <> 0 then print_string "1";
if x land 2 <> 0 then print_string "2";
if x land 4 <> 0 then print_string "4"
You must understand that if ... then is an expression like any other. If no else is present, it must be understood as if ... then ... else () and thus has type unit. To emphasize the fact that it is an expression, suppose you have two functions f and g of type, say, int → int. You can write
(if test then f else g) 1
You must also understand that x :: r does not change r at all, it constructs a new list putting x in front of r (the tail of this list is shared with the list r). In your case, the logic is not clear: what is the result when h=0 but the two if fail?
let rec move_helper b sz r = match b with
| [] -> r
| h :: t ->
if h = 0 then
if h - 1 = sz then (h - 1) :: r
else if h + 1 = sz then (h + 1) :: r
else (* What do you want to return here? *)
else move_helper t sz r
When you have a if, always put an else. Because when you don't put an else, Java will not know if the case is true or false.
I have a set of problems that I've been working through and can't seem to understand what the last one is asking. Here is the first problem, and my solution to it:
a) Often we are interested in computing ∑i=m..n f(i), the sum of function values f(i) for i = m through n. Define sigma f m n which computes ∑i=m..n f(i). This is different from defining sigma (f, m, n).
fun sigma f m n = if (m=n) then f(m) else (f(m) + sigma f (m+1) n);
The second problem, and my solution:
b) In the computation of sigma above, the index i goes from current
i to next value i+1. We may want to compute the sum of f(i) where i
goes from current i to the next, say i+2, not i+1. If we send this
information as an argument, we can compute more generalized
summation. Define ‘sum f next m n’ to compute such summation, where
‘next’ is a function to compute the next index value from the
current index value. To get ‘sigma’ in (a), you send the successor
function as ‘next’.
fun sum f next m n = if (m>=n) then f(m) else (f(m) + sum f (next) (next(m)) n);
And the third problem, with my attempt:
c) Generalizing sum in (b), we can compute not only summation but also
product and other forms of accumulation. If we want to compute sum in
(b), we send addition as an argument; if we want to compute the
product of function values, we send multiplication as an argument for
the same parameter. We also have to send the identity of the
operator. Define ‘accum h v f next m n’ to compute such accumulation,
where h is a two-variable function to do accumulation, and v is the
base value for accumulation. If we send the multiplication function
for h, 1 for v, and the successor function as ‘next’, this ‘accum’
computes ∏i=m..n f(i). Create examples whose ‘h’ is not addition or
multiplication, too.
fun accum h v f next m n = if (m>=n) then f(m) else (h (f(m)) (accum (h) (v) (f) (next) (next(m)) n));
In problem C, I'm unsure of what i'm suppose to do with my "v" argument. Right now the function will take any interval of numbers m - n and apply any kind of operation to them. For example, I could call my function
accum mult (4?) double next3 1 5;
where double is a doubling function and next3 adds 3 to a given value. Any ideas on how i'm suppoes to utilize the v value?
This set of problems is designed to lead to implementation of accumulation function. It takes
h - combines previous value and current value to produce next value
v - starting value for h
f - function to be applied to values from [m, n) interval before passing them to h function
next - computes next value in sequence
m and n - boundaries
Here is how I'd define accum:
fun accum h v f next m n = if m >= n then v else accum h (h (f m) v) f next (next m) n
Examples that were described in C will look like this:
fun sum x y = x + y;
fun mult x y = x * y;
fun id x = x;
accum sum 0 id next 1 10; (* sum [1, 10) staring 0 *)
accum mult 1 id next 1 10; (* prod [1, 10) starting 1 *)
For example, you can calculate sum of numbers from 1 to 10 and plus 5 if you pass 5 as v in first example.
The instructions will make more sense if you consider the possibility of an empty interval.
The "sum" of a single value n is n. The sum of no values is zero.
The "product" of a single value n is n. The product of no values is one.
A list of a single value n is [n] (n::nil). A list of no values is nil.
Currently, you're assuming that m ≤ n, and treating m = n as a special case that returns f m. Another approach is to treat m > n as the special case, returning v. Then, when m = n, your function will automatically return h v (f m), which is the same as (f m) (provided that v was selected properly for this h).
To be honest, though, I think the v-less approach is fine when the function's arguments specify an interval of the form [m,n], since there's no logical reason that such a function would support an empty interval. (I mean, [m,m−1] isn't so much "the empty interval" as it is "obvious error".) The v-ful approach is chiefly useful when the function's arguments specify a list or set of elements in some way that really could conceivably be empty, e.g. as an 'a list.
It is possible to improve "raw" Fibonacci recursive procedure
Fib[n_] := If[n < 2, n, Fib[n - 1] + Fib[n - 2]]
with
Fib[n_] := Fib[n] = If[n < 2, n, Fib[n - 1] + Fib[n - 2]]
in Wolfram Mathematica.
First version will suffer from exponential explosion while second one will not since Mathematica will see repeating function calls in expression and memoize (reuse) them.
Is it possible to do the same in OCaml?
How to improve
let rec fib n = if n<2 then n else fib (n-1) + fib (n-2);;
in the same manner?
The solution provided by rgrinberg can be generalized so that we can memoize any function. I am going to use associative lists instead of hashtables. But it does not really matter, you can easily convert all my examples to use hashtables.
First, here is a function memo which takes another function and returns its memoized version. It is what nlucaroni suggested in one of the comments:
let memo f =
let m = ref [] in
fun x ->
try
List.assoc x !m
with
Not_found ->
let y = f x in
m := (x, y) :: !m ;
y
The function memo f keeps a list m of results computed so far. When asked to compute f x it first checks m to see if f x has been computed already. If yes, it returns the result, otherwise it actually computes f x, stores the result in m, and returns it.
There is a problem with the above memo in case f is recursive. Once memo calls f to compute f x, any recursive calls made by f will not be intercepted by memo. To solve this problem we need to do two things:
In the definition of such a recursive f we need to substitute recursive calls with calls to a function "to be provided later" (this will be the memoized version of f).
In memo f we need to provide f with the promised "function which you should call when you want to make a recursive call".
This leads to the following solution:
let memo_rec f =
let m = ref [] in
let rec g x =
try
List.assoc x !m
with
Not_found ->
let y = f g x in
m := (x, y) :: !m ;
y
in
g
To demonstrate how this works, let us memoize the naive Fibonacci function. We need to write it so that it accepts an extra argument, which I will call self. This argument is what the function should use instead of recursively calling itself:
let fib self = function
0 -> 1
| 1 -> 1
| n -> self (n - 1) + self (n - 2)
Now to get the memoized fib, we compute
let fib_memoized = memo_rec fib
You are welcome to try it out to see that fib_memoized 50 returns instantly. (This is not so for memo f where f is the usual naive recursive definition.)
You pretty much do what the mathematica version does but manually:
let rec fib =
let cache = Hashtbl.create 10 in
begin fun n ->
try Hashtbl.find cache n
with Not_found -> begin
if n < 2 then n
else
let f = fib (n-1) + fib (n-2) in
Hashtbl.add cache n f; f
end
end
Here I choose a hashtable to store already computed results instead of recomputing them.
Note that you should still beware of integer overflow since we are using a normal and not a big int.
I have this complex iterations program I wrote in TI Basic to perform a basic iteration on a complex number and then give the magnitude of the result:
INPUT “SEED?”, C
INPUT “ITERATIONS?”, N
C→Z
For (I,1,N)
Z^2 + C → Z
DISP Z
DISP “MAGNITUDE”, sqrt ((real(Z)^2 + imag(Z)^2))
PAUSE
END
What I would like to do is make a Haskell version of this to wow my teacher in an assignment. I am still only learning and got this far:
fractal ::(RealFloat a) =>
(Complex a) -> (Integer a) -> [Complex a]
fractal c n | n == a = z : fractal (z^2 + c)
| otherwise = error "Finished"
What I don't know how to do is how to make it only iterate n times, so I wanted to have it count up a and then compare it to n to see if it had finished.
How would I go about this?
Newacct's answer shows the way:
fractal c n = take n $ iterate (\z -> z^2 + c) c
Iterate generates the infinite list of repeated applications.
Ex:
iterate (2*) 1 == [1, 2, 4, 8, 16, 32, ...]
Regarding the IO, you'll have to do some monadic computations.
import Data.Complex
import Control.Monad
fractal c n = take n $ iterate (\z -> z^2 + c) c
main :: IO ()
main = do
-- Print and read (you could even omit the type signatures here)
putStr "Seed: "
c <- readLn :: IO (Complex Double)
putStr "Number of iterations: "
n <- readLn :: IO Int
-- Working with each element the result list
forM_ (fractal c n) $ \current -> do
putStrLn $ show current
putStrLn $ "Magnitude: " ++ (show $ magnitude current)
Since Complex is convertible from and to strings by default, you can use readLn to read them from the console (format is Re :+ Im).
Edit: Just for fun, one could desugar the monadic syntax and type signatures which would compress the whole programm to this:
main =
(putStr "Seed: ") >> readLn >>= \c ->
(putStr "Number of iterations: ") >> readLn >>= \n ->
forM_ (take n $ iterate (\z -> z^2 + c) c) $ \current ->
putStrLn $ show current ++ "\nMagnitude: " ++ (show $ magnitude current)
Edit #2: Some Links related to plotting and Mandelbrot's sets.
Fractal plotter
Plotting with
Graphics.UI
Simplest solution
(ASCII-ART)
Well you can always generate an infinite list of results of repeated applications and take the first n of them using take. And the iterate function is useful for generating an infinite list of results of repeated applications.
If you'd like a list of values:
fractalList c n = fractalListHelper c c n
where
fractalListHelper z c 0 = []
fractalListHelper z c n = z : fractalListHelper (z^2 + c) c (n-1)
If you only care about the last result:
fractal c n = fractalHelper c c n
where
fractalHelper z c 0 = z
fractalHelper z c n = fractalHelper (z^2 + c) c (n-1)
Basically, in both cases you need a helper function to the counting and accumulation. Now I'm sure there's a better/less verbose way to do this, but I'm pretty much a Haskell newbie myself.
Edit: just for kicks, a foldr one-liner:
fractalFold c n = foldr (\c z -> z^2 + c) c (take n (repeat c))
(although, the (take n (repeat c)) thing seems kind of unnecessary, there has to be an even better way)