I'm trying to write a Maxima function that iterates another function provided as an argument. The goal is basically...
iter(f,0) ........ gives the identity function lambda([x],x)
iter(f,1) ........ gives f
iter(f,2) ........ gives lambda([x],f(f(x))
iter(f,3) ........ gives lambda([x],f(f(f(x)))
The reason is trying to figure out how an iterated polynomial behaves - similar to the Robert May population equation, but a different polynomial.
Anyway, I'm very new to Maxima (at least to things that seem more like simple programming than just asking for a solution) and after some time trying to figure out what I'm doing wrong, I think I've eliminated all silly mistakes and I must have a more fundamental misunderstanding of how Maxima works.
What I have...
iter(f,n) := if is (n=0)
then lambda ([x], x)
else block ([n2: floor (n/2),
nr: is (n2*2#n),
ff: iter (f,n2) ], if nr then lambda ([x],f(ff(ff(x))))
else lambda ([x], ff(ff(x)) ));
Maxima accepts this. Now as a simple example function to iterate...
inc(x):=x+1;
And some tests - first the base case...
iter(inc,0);
That works - it gives lambda([x],x) as expected. Next, "iterating" one time...
iter(inc,1);
I'm expecting something equivalent to inc, but because of the way this is written, more like lambda([x],inc(identity(identity(x))) but with more clutter. What I'm actually getting is a stack overflow...
Maxima encountered a Lisp error:
Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.
...
I can't see why the is (n=0) base-case check would fail to spot that in the recursive call, so I can't see why this iter function would be entered more than twice for n=1 - it seems pretty extreme for that the exhaust the stack.
Of course once I have the basic idea working I'll probably special-case n=1 as effectively another base case for efficiency (a less cluttered resulting function definition) and add more checks, but I just want something that doesn't stack-overflow in trivial cases for now.
What am I misunderstanding?
Here's what I came up with. It's necessary to substitute into the body of lambda since the body is not evaluated -- I guess you have encountered this important point already.
(%i3) iter(f, n) := if n = 0 then identity elseif n = 1 then f
else subst([ff = iter(f, n - 1),'f = f],
lambda([x], f(ff(x)))) $
(%i4) iter(inc, 0);
(%o4) identity
(%i5) iter(inc, 1);
(%o5) inc
(%i6) iter(inc, 2);
(%o6) lambda([x], inc(inc(x)))
(%i7) iter(inc, 3);
(%o7) lambda([x], inc(inc(inc(x))))
(%i8) iter(inc, 4);
(%o8) lambda([x], inc(inc(inc(inc(x)))))
(%i9) inc(u) := u + 1 $
(%i10) iter(inc, 4);
(%o10) lambda([x], inc(x + 3))
(%i11) %(10);
(%o11) 14
(%i12) makelist (iter(cos, k), k, 0, 10);
(%o12) [identity, cos, lambda([x], cos(cos(x))),
lambda([x], cos(cos(cos(x)))), lambda([x],
cos(cos(cos(cos(x))))), lambda([x], cos(cos(cos(cos(cos(x)))))),
lambda([x], cos(cos(cos(cos(cos(cos(x))))))),
lambda([x], cos(cos(cos(cos(cos(cos(cos(x)))))))),
lambda([x], cos(cos(cos(cos(cos(cos(cos(cos(x))))))))),
lambda([x], cos(cos(cos(cos(cos(cos(cos(cos(cos(x)))))))))),
lambda([x], cos(cos(cos(cos(cos(cos(cos(cos(cos(cos(x)))))))))))]
(%i13) map (lambda([f], f(0.1)), %);
(%o13) [0.1, 0.9950041652780257, 0.5444993958277886,
0.8553867058793604, 0.6559266636704799, 0.7924831019448093,
0.7020792679906703, 0.7635010336918854, 0.7224196362389732,
0.7502080588752906, 0.731547032044224]
Maxima is almost good at stuff like this -- since it is built on top of Lisp, the right conceptual elements are present. However, the lack of lexical scope is a serious problem when working on problems like this, because it means that when you refer to f within a function definition, it is the same f which might exist outside of it. When the solution depends on carefully distinguishing which f you mean, that's a problem.
Anyway as it stands I hope this solution is useful to you in some way.
Earlier, after a moment of inspiration, I tried the following in Maxima...
block([a:1,b:a],b);
This gave me a where I was expecting 1, which suggests that the b:a variable definition cannot see the a:1 variable definition earlier in the same block. I had assumed that later variable definitions in a block would be able to see earlier definitions, and that affects two variable definitions in my iter function - in particular, iter (f,n2) cannot see the definition of n2 which breaks the base-case check in the recursion.
What I have now (WARNING - NOT A WORKING SOLUTION) is...
iter(f,n) := if is (n=0)
then lambda ([x], x)
else block ([n2: floor (n/2)],
block ([g: iter (f,n2)],
if is (n2*2#n) then lambda ([x],f(g(g(x))))
else lambda ([x], g(g(x)) )));
I'm nesting one block inside another so that the later variable definition can see the earlier one. There is no nr (n was rounded?) variable, though TBH keeping that wouldn't have required a third nested block. I replaced ff with g at some point.
This solves the stack overflow issue - the base case of the recursion seems to be handled correctly now.
This still isn't working - it seems like the references to g now cannot see the definition of g for some reason.
iter(inc,0) ................. lambda([x],x)
iter(inc,1) ................. lambda([x],f(g(g(x))))
iter(inc,2) ................. lambda([x],g(g(x)))
...
When the recursive half-size iteration g is needed, for some reason it's not substituted. Also noticable - neither is f substituted.
As a best guess, this is probably due to the function calls being by-name in the generated lambda, and due to nothing forcing them to be substituted in or forcing the overall expression to be simplified.
(update - This SO question suggests I've understood the problem, but the solution doesn't appear to work in my case - what I'm trying to substitute is referenced via a variable no matter what.)
But it's also a different question (it's not a recursion/stack overflow issue) so I'll come back and ask another question if I can't figure it out. I'll also add a working solution here if/when I figure it out.
I tried a few more approaches using subst and the double-quote notation, but Maxima stubbornly kept referring to f and g by name. After a little thought, I switched approach - instead of generating a function, generate an expression. The working result is...
iter(v,e,n) := if is (n=0)
then ''v
else block ([n2: floor (n/2)],
block ([g: iter (v,e,n2)],
block ([gg: subst([''v=g], g)],
if is (n2*2#n) then subst([''v=e], gg)
else gg )));
The three nested block expressions are annoying - I'm probably still missing something that's obvious to anyone with any Maxima experience. Also, this is fragile - it probably needs some parameter checks, but not on every recursive call. Finally, it doesn't simplify result - it just builds an expression by applying direct substitution into itself.
What if you do everything with expressions?
(%i1) iter(e, n):= block([ans: e], thru n - 1 do ans: subst('x = e, ans), ans) $
(%i2) iter(x^2 + x, 1);
2
(%o2) x + x
(%i3) iter(x^2 + x, 2);
2 2 2
(%o3) (x + x) + x + x
(%i4) iter(x^2 + x, 3);
2 2 2 2 2 2 2
(%o4) ((x + x) + x + x) + (x + x) + x + x
You can define a function at the end:
(%i5) define(g(x), iter(x^2 + x, 3));
Related
I am implementing a recursive program to calculate the certain values in the Schroder sequence, and I'm having two problems:
I need to calculate the number of calls in the program;
Past a certain number, the program will generate incorrect values (I think it's because the number is too big);
Here is the code:
let rec schroder n =
if n <= 0 then 1
else if n = 1 then 2
else 3 * schroder (n-1) + sum n 1
and sum n k =
if (k > n-2) then 0
else schroder k * schroder (n-k-1) + sum n (k+1)
When I try to return tuples (1.), the function sum stops working because it's trying to return int when it has type int * int;
Regarding 2., when I do schroder 15 it returns:
-357364258
when it should be returning
3937603038.
EDIT:
firstly thanks for the tips, secondly after some hours of deep struggle, i manage to create the function, now my problem is that i'm struggling to install zarith. I think I got it installed, but ..
in terminal when i do ocamlc -I +zarith test.ml i get an error saying Required module 'Z' is unavailable.
in utop after doing #load "zarith.cma";; and #install_printer Z.pp_print;; i can compile, run the function and it works. However i'm trying to implement a Scanf.scanf so that i can print different values of the sequence. With this being said whenever i try to run the scanf, i dont get a chance to write any number as i get a message saying that '\\n' is not a decimal digit.
With this being said i will most probably also have problems with printing the value, because i dont think that i'm going to be able to print such a big number with a %d. The let r1,c1 = in the following code, is a example of what i'm talking about.
Here's what i'm using :
(function)
..
let v1, v2 = Scanf.scanf "%d %d" (fun v1 v2-> v1,v2);;
let r1,c1 = schroder_a (Big_int_Z.of_int v1) in
Printf.printf "%d %d\n" (Big_int_Z.int_of_big_int r1) (Big_int_Z.int_of_big_int c1);
let r2,c2 = schroder_a v2 in
Printf.printf "%d %d\n" r2 c2;
P.S. 'r1' & 'r2' stands for result, and 'c1' and 'c2' stands for the number of calls of schroder's recursive function.
P.S.S. the prints are written differently because i was just testing, but i cant even pass through the scanf so..
This is the third time I've seen this problem here on StackOverflow, so I assume it's some kind of school assignment. As such, I'm just going to make some comments.
OCaml doesn't have a function named sum built in. If it's a function you've written yourself, the obvious suggestion would be to rewrite it so that it knows how to add up the tuples that you want to return. That would be one approach, at any rate.
It's true, ints in OCaml are subject to overflow. If you want to calculate larger values you need to use a "big number" package. The one to use with a modern OCaml is Zarith (I have linked to the description on ocaml.org).
However, none of the other people solving this assignment have mentioned overflow as a problem. It could be that you're OK if you just solve for representable OCaml int values.
3937603038 is larger than what a 32-bit int can hold, and will therefore overflow. You can fix this by using int64 instead (until you overflow that too). You'll have to use int64 literals, using the L suffix, and operations from the Int64 module. Here's your code converted to compute the value as an int64:
let rec schroder n =
if n <= 0 then 1L
else if n = 1 then 2L
else Int64.add (Int64.mul 3L (schroder (n-1))) (sum n 1)
and sum n k =
if (k > n-2) then 0L
else Int64.add (Int64.mul (schroder k) (schroder (n-k-1))) (sum n (k+1))
I need to calculate the number of calls in the program;
...
the function 'sum' stops working because it's trying to return 'int' when it has type 'int * int'
Make sure that you have updated all the recursive calls to shroder. Remember it is now returning a pair not a number, so you can't, for example, just to add it and you need to unpack the pair first. E.g.,
...
else
let r,i = schroder (n-1) (i+1) in
3 * r + sum n 1 and ...
and so on.
Past a certain number, the program will generate incorrect values (I think it's because the number is too big);
You need to use an arbitrary-precision numbers, e.g., zarith
Im trying to figure out an equation. This is f(n)=f(n-1) + 3n^2 - n. I also have the values to use as f(1), f(2), f(3). How would i go about solving this??
You would usually use recursion but, whether you do that or an iterative solution, you're missing (or simply haven't shown us) a vital bit of information, the terminating condition such as f(1) = 1 (for example).
With that extra piece of information, you could code up a recursive solution relatively easily, such as the following pseudo-code:
define f(n):
if n == 1:
return 1
return f(n-1) + (3 * n * n) - n
As an aside, that's not actually Fibonacci, which is the specific 1, 1, 2, 3, 5, 8, 13, ... sequence.
It can be said to be Fibonacci-like but it's actually more efficient to do this one recursively since it only involves one self-referential call per level whereas Fibonacci needs two:
define f(n):
if n <= 2:
return 1
return f(n-2) + f(n-1)
And if you're one of those paranoid types who doesn't like recursion (and I'll admit freely it can have its problems in the real world of limited stack depths), you could opt for the iterative version.
define f(n):
if n == 1:
return 1
parent = 1
for num = 2 to n inclusive:
result = parent + (3 * num * num) - num
parent = result
return result
If you ask this question on a programming site such as Stack Overflow, you can expect to get code as an answer.
On the other hand, if you are looking for a closed formula for f(n), then you should direct your question to a specialised StackExchange site such as Computer Science.
Note: what you are looking for is called the repertoire method. It can be used to solve your problem (the closed formula is very simple).
I'm a newcomer to J and I've been trying to create a Fibonacci function as an exercise (always the second function I create when learning a language). I just can't figure out what exactly is wrong in my way of doing it. I have tried to define it as tacit, but it gets hung if argument is greater than one.
fib =: [ ` (($: (]-1)) + ($: (]-2))) #. (>&1)
I've also attempted to create it explicitly, and that worked fine.
fib =: 3 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
I tried to create a tacit out of that by replacing 3 with 13, but it threw an error.
fib =: 13 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
|spelling error
| if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.
| ^
| fib=: 13 :'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
So, I'm asking for someone to explain what exactly I am doing wrong here.
Here's an alternative that I think is both clearer and more concise:
fibn =: (-&2 +&$: -&1)^:(1&<) M."0
Compare with a more canonical (pseudocode) definition:
fib(n) = fib(n-1) + fib(n-2) if n > 2 else n
First, instead of using [ ` with #. (>&1), which uses a gerund, it's better to use ^:(1&<). For f(n) if cond(n) else n, using the ^: conjunction is more idiomatic; ^:0 means "do nothing" and ^:1 means "do once," so the intent is clear. #. is better suited to nontrivial behavior.
Second, using the & bond/compose conjunction simplifies the train significantly. Repeated uses of [: and ] are rather confusing and opaque. Refactoring using & puts together related operations: first, split n into two, namely n-2 and n-1, and second, add together the fibn of those two numbers.
And, lastly, "0 for list handling and M. for memoizing. M. is rather important from a performance perspective, as a straightforward implementation of the canonical definition will call fib(2) excessively. You can have your cake (a simple definition) and eat it too (good performance) with the built-in memoization adverb.
Source for this particular definition: f0b on this page.
Okay, I found it. I ran only the recursive block through tacit generator and got this block.
13 : '(f y-1) + (f y-2)'
([: f 1 -~ ]) + [: f 2 -~ ]
Then I inserted that to the original piece, getting this.
fib =: [ ` (([: $: 1 -~ ]) + [: $: 2 -~ ]) #. (>&1)
And that works like a charm. I also inserted " 0 to the end to make it accept lists.
I'm new to prolog. I'm doing a recursive program the problem is that even though it prints the answer.. it doesn't stop after printing the answer and eventually gives "Out of local stack".
I've read it could be a left recursion issue but as I've already told you I'm new to prolog and I don't really understand what happens...
so.. here's code.
f(X, Y):-
Y is sqrt(1-((X-1)*(X-1))).
sum(SEGMENTS, 1, TOTAL):-
f(2/SEGMENTS*1,H1),
TOTAL is (2/SEGMENTS)*H1.
sum(SEGMENTS, NR, TOTAL):-
N1 is (NR-1),
sum(SEGMENTS, N1, S1),
f(2/SEGMENTS*NR,H1),
f(2/SEGMENTS*N1,H2),
TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).
It's supposed to calculate a semicircle area with the trapezoid rule or something similar.
As I've already told you .. it does finishes but after getting to the base case sum(segments, 1, total) it calls the function with the second alternative... :S
Thanks guys!
Also: Here's what I get when I run it
?- sum(3000,3000,TOTAL).
TOTAL = 1.5707983753431007 ;
ERROR: Out of local stack
The problem is that backtracking will attempt the case of NR value of 1 on the second sum clause after the first clause has succeeded. This causes a long recursion process (since NR is being decremented continually for each recursive call, attempting to wrap around through all negative integer values, etc).
A simple way to resolve the problem is in your second sum clause. Since the intention is that it is for the case of NR > 1, put NR > 1 as your first statement:
sum(SEGMENTS, NR, TOTAL) :-
NR > 1,
N1 is (NR-1),
sum(SEGMENTS, N1, S1),
f(2/SEGMENTS*NR,H1),
f(2/SEGMENTS*N1,H2),
TOTAL is S1 + (2/SEGMENTS)*((H1+H2)/2).
Also note that the expression f(2/SEGMENTS*NR, H1) doesn't compute the expression 2/SEGMENTS*NR and pass it to f. It actually passes that expression symbolically. It just happens to work here because f includes it on the right hand side of an is/2 so it is evaluated as desired. If you trace it, you'll see what I mean.
Recently I have been studying recursion; how to write it, analyze it, etc. I have thought for a while that recurrence and recursion were the same thing, but some problems on recent homework assignments and quizzes have me thinking there are slight differences, that 'recurrence' is the way to describe a recursive program or function.
This has all been very Greek to me until recently, when I realized that there is something called the 'master theorem' used to write the 'recurrence' for problems or programs. I've been reading through the wikipedia page, but, as usual, things are worded in such a way that I don't really understand what it's talking about. I learn much better with examples.
So, a few questions:
Lets say you are given this recurrence:
r(n) = 2*r(n-2) + r(n-1);
r(1) = r(2)
= 1
Is this, in fact, in the form of the master theorem? If so, in words, what is it saying? If you were to be trying to write a small program or a tree of recursion based on this recurrence, what would that look like? Should I just try substituting numbers in, seeing a pattern, then writing pseudocode that could recursively create that pattern, or, since this may be in the form of the master theorem, is there a more straightforward, mathematical approach?
Now, lets say you were asked to find the recurrence, T(n), for the number of additions performed by the program created from the previous recurrence. I can see that the base case would probably be T(1) = T(2) = 0, but I'm not sure where to go from there.
Basically, I am asking how to go from a given recurrence to code, and the opposite. Since this looks like the master theorem, I'm wondering if there is a straightforward and mathematical way of going about it.
EDIT: Okay, I've looked through some of my past assignments to find another example of where I'm asked, 'to find the recurrence', which is the part of this question I'm having the post trouble with.
Recurrence that describes in the best
way the number of addition operations
in the following program fragment
(when called with l == 1 and r == n)
int example(A, int l, int r) {
if (l == r)
return 2;
return (A[l] + example(A, l+1, r);
}
A few years ago, Mohamad Akra and Louay Bazzi proved a result that generalizes the Master method -- it's almost always better. You really shouldn't be using the Master Theorem anymore...
See, for example, this writeup: http://courses.csail.mit.edu/6.046/spring04/handouts/akrabazzi.pdf
Basically, get your recurrence to look like equation 1 in the paper, pick off the coefficients, and integrate the expression in Theorem 1.
Zachary:
Lets say you are given this
recurrence:
r(n) = 2*r(n-2) + r(n-1); r(1) = r(2)
= 1
Is this, in fact, in the form of the
master theorem? If so, in words, what
is it saying?
I think that what your recurrence relation is saying is that for function of "r" with "n" as its parameter (representing the total number of data sets you're inputting), whatever you get at the nth position of the data-set is the output of the n-1 th position plus twice whatever is the result of the n-2 th position, with no non-recursive work being done. When you try to solve a recurrence relation, you're trying to go about expressing it in a way that doesn't involve recursion.
However, I don't think that that is in the correct form for the Master Theorem Method. Your statement is a "second order linear recurrence relation with constant coefficients". Apparently, according to my old Discrete Math textbook, that's the form you need to have in order to solve the recurrence relation.
Here's the form that they give:
r(n) = a*r(n-1) + b*r(n-2) + f(n)
For 'a' and 'b' are some constants and f(n) is some function of n. In your statement, a = 1, b = 2, and f(n) = 0. Whenever, f(n) is equal to zero the recurrence relation is known as "homogenous". So, your expression is homogenous.
I don't think that you can solve a homogenous recurrence relation using the Master Method Theoerm because f(n) = 0. None of the cases for Master Method Theorem allow for that because n-to-the-power-of-anything can't equal zero. I could be wrong, because I'm not really an expert at this but I don't that it's possible to solve a homogenous recurrence relation using the Master Method.
I that that the way to solve a homogeneous recurrence relation is to go by 5 steps:
1) Form the characteristic equation, which is something of the form of:
x^k - c[1]*x^k-1 - c[2]*x^k-2 - ... - c[k-1]*x - c[k] = 0
If you've only got 2 recursive instances in your homogeneous recurrence relation then you only need to change your equation into the Quadratic Equation where
x^2 - a*x - b = 0
This is because a recurrence relation of the form of
r(n) = a*r(n-1) + b*r(n-2)
Can be re-written as
r(n) - a*r(n-1) - b*r(n-2) = 0
2) After your recurrence relation is rewritten as a characteristic equation, next find the roots (x[1] and x[2]) of the characteristic equation.
3) With your roots, your solution will now be one of the two forms:
if x[1]!=x[2]
c[1]*x[1]^n + c[2]*x[2]^n
else
c[1]*x[1]^n + n*c[2]*x[2]^n
for when n>2.
4) With the new form of your recursive solution, you use the initial conditions (r(1) and r(2)) to find c[1] and c[2]
Going with your example here's what we get:
1)
r(n) = 1*r(n-1) + 2*r(n-2)
=> x^2 - x - 2 = 0
2) Solving for x
x = (-1 +- sqrt(-1^2 - 4(1)(-2)))/2(1)
x[1] = ((-1 + 3)/2) = 1
x[2] = ((-1 - 3)/2) = -2
3) Since x[1] != x[2], your solution has the form:
c[1](x[1])^n + c[2](x[2])^n
4) Now, use your initial conditions to find the two constants c[1] and c[2]:
c[1](1)^1 + c[2](-2)^1 = 1
c[1](1)^2 + c[2](-2)^2 = 1
Honestly, I'm not sure what your constants are in this situation, I stopped at this point. I guess you'd have to plug in numbers until you'd somehow got a value for both c[1] and c[2] which would both satisfy those two expressions. Either that or perform row reduction on a matrix C where C equals:
[ 1 1 | 1 ]
[ 1 2 | 1 ]
Zachary:
Recurrence that describes in the best
way the number of addition operations
in the following program fragment
(when called with l == 1 and r == n)
int example(A, int l, int r) {
if (l == r)
return 2;
return (A[l] + example(A, l+1, r);
}
Here's the time complexity values for your given code for when r>l:
int example(A, int l, int r) { => T(r) = 0
if (l == r) => T(r) = 1
return 2; => T(r) = 1
return (A[l] + example(A, l+1, r); => T(r) = 1 + T(r-(l+1))
}
Total: T(r) = 3 + T(r-(l+1))
Else, when r==l then T(r) = 2, because the if-statement and the return both require 1 step per execution.
Your method, written in code using a recursive function, would look like this:
function r(int n)
{
if (n == 2) return 1;
if (n == 1) return 1;
return 2 * r(n-2) + r(n-1); // I guess we're assuming n > 2
}
I'm not sure what "recurrence" is, but a recursive function is simply one that calls itself.
Recursive functions need an escape clause (some non-recursive case - for example, "if n==1 return 1") to prevent a Stack Overflow error (i.e., the function gets called so much that the interpreter runs out of memory or other resources)
A simple program that would implement that would look like:
public int r(int input) {
if (input == 1 || input == 2) {
return 1;
} else {
return 2 * r(input - 2) + r(input -1)
}
}
You would also need to make sure that the input is not going to cause an infinite recursion, for example, if the input at the beginning was less than 1. If this is not a valid case, then return an error, if it is valid, then return the appropriate value.
"I'm not exactly sure what 'recurrence' is either"
The definition of a "recurrence relation" is a sequence of numbers "whose domain is some infinite set of integers and whose range is a set of real numbers." With the additional condition that that the function describing this sequence "defines one member of the sequence in terms of a previous one."
And, the objective behind solving them, I think, is to go from a recursive definition to one that isn't. Say if you had T(0) = 2 and T(n) = 2 + T(n-1) for all n>0, you'd have to go from the expression "T(n) = 2 + T(n-1)" to one like "2n+2".
sources:
1) "Discrete Mathematics with Graph Theory - Second Edition", by Edgar G. Goodair and Michael M. Parmenter
2) "Computer Algorithms C++," by Ellis Horowitz, Sartaj Sahni, and Sanguthevar Rajasekaran.