Walking through the recursive factorial program in Prolog? - recursion

I'm really having a hard time understanding how the recursion works in Prolog.
factorial(0,1).
factorial(N,F) :-
N>0,
N1 is N-1,
factorial(N1,F1),
F is N * F1.
I understand the first part is the base case and that would end the continuation of the program. However, the part that confuses me is the parameters of the second factorial call (N1, F1). Can someone explain the steps of how everything is executed and calculated?

The second rule basically says that F is the factorial of N if N is greater than zero and there is a number N1 which is the result of N-1 and F1 is the factorial of N1 and F is the product of N and F1.
Example
Let's say that you want to find the factorial of 3.
-? factorial(3,F).
Prolog puts factorial(3,F) on the stack of goals and then looks for rules whose head match the first goal. There are two rules for factorial/2 (the fact factorial(0,1) can be seen as a rule without body), but for the first 0 does not unify with 5 so it cannot be used. The second unifies with N being instantiated to 5 and Prolog adds the conditions to the stack which becomes:
3 > 0, N1 is 3-1, factorial(N1,F1), F is 3*F1
The first goal is satisfied as 3 is greater than zero. The second one is satisfied by binding N1 to the result of the arithmetic evaluation of 3-1 so the stack of goals is now:
factorial(2,F1), F is 3*F1
Again, Prolog looks for rules that might be used to satisfy factorial(2,F1) and uses the second one (N unifies with 2 and F with F1 and different names are used for the variables) :
2 > 0, N2 is 2-1, factorial(N2,F2), F1 is 2*F2, F is 3*F1
Next, 2 > 0 is true and N2 is unified with the arithmetic result of 2-1 so the stack of goals becomes:
factorial(1,F2), F1 is 2*F2, F is 3*F1
Using again the second rule for factorial/2:
1 > 0, N3 is 1-1, factorial(N3,F3), F2 is 1*F3, F1 is 2*F2, F is 3*F1
N3 becomes zero (when N3 is 1-1 is being satisfied):
factorial(0,F3), F2 is 1 * F3, F1 is 2*F2, F is 3*F1
At this point, the first rule for factorial/2 can be used to satisfy factorial(0, F3), but a choice point is created as there are more rules that can be used. So, factorial(0,F3) succeeds by instantiating F3 to 1.
F2 is 1 * 1, F1 is 2 * F2, F is 3 * F3
By satisfying all the goals left on the stack, F becomes 6 and you get your first solution. But, there was a choice point for factorial(0, F3). The second rule can be used at that point:
0>0, N4 is 0-1, factorial(N4,F4), F3 is 0*F4, F2 is 1*F3, F1 is 2*F2, F is 3*F3
But 0>0 fails and the execution stops as there where no other choice points to backtrack to.
You can avoid leaving that useless choice point for factorial(0,_) by using a [green] cut operator.
factorial(0, 1) :- !.

Related

Propositional logic, logical equivalent

a) Determine whether the following statement forms are logically equivalent:
p -> (q -> r) and (p -> q) -> r
b) Use the logical equivalence established in part (a) to rewrite the following sentence in two different ways. (Assume that n represents a fixed integer.)
If n is prime, then n is odd or n is 2.
Can someone help me with the B one? its really confusing
If n is prime, then n is odd or n is 2.
The question is asking you to rewrite the sentence in two different ways in English
If n is prime and n is not odd, then n is 2.
If n is prime and n is not 2, then n is odd.
The following links do a better job of explaining it:
Logically_Equivalent_Statements
Exercises on Logic of Compound Statements and Valid Arguments

How does the Peano axiom construct only the set of Natural numbers but no other set

I am beginning real analysis and stacked on the first page (Peano Postulates)
It reads as follows at least on my textbook.
Axiom 1.2.1 (Peano Postulates). There exists a set N with an element 1 E N and a function s: N -> N that satisfy the following three properties.
a. There is no n E N such that s(n) = 1
b. The function s is injective.
c. Let G is subset of N be as set. Suppose that 1 E G, and that g E G then s(g) E G. Then G = N.
Definition 1.2.2. The set of natural numbers, denoted N, is the set the existence of which is given in the Peano Postulates.
My question is, from my understanding of the postulates we could construct infinite set which satisfy the three properties.
For example
Odd = {1,3,5,6,...} or
or = {1,5,25,635....} with a different s(n) off course, but s(n) is not defined anyway in the postulates.
How is those properties uniquely identify the set of the Natural numbers?

White-box and Black-box testing of recursive functions

I learned white-box and black-box testing in terms of iterative functions. Now i need to do white-box and black-box testing of several recursive functions (in F#). take the following recursive algorithm for gcd:
gcd (m, n)
if (m % n) = 0 then
n
else
gcd n ( m % n)
For the white-box test: how exactly do i go about covering the different branches of the algorithm? Naively one could say there are two branches but when the function is called more than once the possible branches will obviously increase. Should i do testing with arguments which results in different amounts of recursive calls or how exactly do i determine which values to test with?
black-box: i get the general idea of black box testing. we should look at possible values we might want to call the function with without having knowledge of its inner workings. In this case i am just not sure which are values we might want to call it with. one way could be just to start with two values m and n for which gcd = 1 and then do the same for values m and for which gcd = 2 up to some gcd= n for some arbitrary number n. Is this how one is supposed to go about this?
First of all, I don't think there is one single established definition of how to do white-box and black-box testing of recursive functions, but here is how I interpret it.
White-box testing. We want to test the function based on its inner working. In case of recursive functions, I think this means that we want to test that the recursive calls it makes are the ones we would expect. One way to do this is to log all recursive calls. A simple implementation of gcd that does this adds a parameter to keep a log and returns it with the result:
let rec gcd log m n =
let log = (m, n)::log
if (m % n) = 0 then List.rev log, n
else gcd log n (m % n)
Now, for some two parameters, say 54 and 22, you can do the calculation by hand, decide what the parameters of the recursive calls should be and write a test for that:
let log, res = gcd [] 54 22
log |> shouldEqual [ (54, 22); (22, 10); (10, 2) ]
Black-box testing. Here, we assume we do not know how exactly the function works, so we cannot test its internals. All we can do is to test it using a number of inputs. It is probably a good idea to think of corner-case or tricky inputs because those are the ones that could cause problems. Given a simple implementation:
let rec gcd m n =
if (m % n) = 0 then n
else gcd n (m % n)
I would probably write tests for the following:
// A random case where one of the numbers is the result
gcd 100 50 |> shouldEqual 50
gcd 50 100 |> shouldEqual 50
// A random case where the only divisor is 1
gcd 13 123 |> shouldEqual 1
gcd 123 13 |> shouldEqual 1
// The following are problematic and I'm not sure what the right behaviour is
gcd 0 0 // This probably should not be allowed
gcd 10 -5 // This returns -5, but I'm not sure that's what we want
Random testing.
You could also use random testing (which is a form of black box testing) to generate multiple test cases automatically. There are at least two random tests I can think of:
Generate two random numbers, a and b and check that gcd a b = gcd b a. This is testing only a very basic property, but it can cover quite a lot of cases.
Pick a random number a and a couple of primes p1, p2, .... Then split the primes into two groups and produce a*p1*p3*p5 and a*p2*p4*p6. Write a test that checks that the GCD of the two numbers is a.

Recursive formula for recurrence that takes 2 arguments

I can create a recursive formula from recurrences where it only passes down one argument (something like $T(n/2)$). However, for a case like this where the value of $u$ and $v$ are different, how do I put them together? This is the problem:
The call to recursive function RecursiveFunction(n, n) for some n > 2
RecursiveFunction(a, b)
if a >= 2 and b >= 2
u=a/2
v=b-1
RecursiveFunction(u, v)
The end goal is to find the tight asymptotic bounds for the worst-case running time, but I just need a formula to start first.
There are in fact two different answers to this, depending on the relative sizes of a and b.
The function can be written as follows:
Where C is some constant work done per call (if statement, pushing u, v onto the call stack etc.). Since the two variables evolve independently, we can analyse their evolution separately.
a - consider the following function:
Expanding the iterative case by m times:
The stopping condition a < 2 is such that:
b - as before:
The complexity of T(a, b) thus depends on which variable reaches its stopping condition first, i.e. the smallest between m and n:

Why is this J function not running?

I am attempting to learn J and the book I am using says this is the proper way to define a monadic function
function =: 3:0
function statements
so I followed this format and wrote the folding code. Can you tell me why this is throwing a syntax error when I try to call it with input but if I just call p it returns 3
h=:>:#i.#<.#-: :[: NB. gets all integers less than half of the input :[: forces error if used dyadicly
d=:(0&=|)~ h :[: NB. gets list where if one is set that index from h was a factor of the input y :[: forces error if used dyadicly
p=: 3:0 NB. tells us p is a monadic function
t =: d y
a =: i. 1
while. 1<#t
if. t~:0
a =: a, #t
end.
t=: _1 }. t NB. found first mistake wrong bracket but fixing that doesn't fix it
end.
a*1
)
NB. p gets a list of all integers that are factors of y
p 4
| syntax error
| p 4
p
3
NB. h and d run fine
h 4
1 2
h 7
1 2 3
d 7
1 0 0
d 4
1 1
Firstly, 3:0 parses like (3:) (0), i.e. the monad "3:" applied to the noun "0". That's not what you want; for definitions, you want to use the dyad ":", so you need to separate it from the 3 with a space.
Secondly, you should use =. instead of =: inside the definition, as t and a are local variables.
Several parts can be simplified:
d =: 0 = h | [ NB. does h y divide y
p =: d # h NB. select d y from h y
Same functionality as before, but clearer and faster.
I figured it out sort of I get a stack error instead of a syntax error with monad define instead of using 3:0. I still have to work out a few kinks but I'm making progress.
h =:>:#i.#<.#-:
d =:(0&=#|)~ h
p =: monad define
t =: d y
a =: i.0
while. 1<#t do.
if. {:t~:0 do.
a=:a, #t
end.
t=: _1 }. t
end.
a
)
my latest attempt is a good deal close getting a value error now. Still not sure why its failing but I'll get it soon. I figured it out I was forgetting the required do. after the conditionals adding them fixes everything.

Resources