Prolog recursively multiply - recursion

I'm trying to multiply two numbers in Prolog recursively i.e. 3*4 = 3+3+3+3 = 12.
My code is :
mult(0,Y,Y).
mult(X,Y,Z) :-
NewX is X-1,
Z is Y + mult(NewX,Y,Z).
but I keep either in an infinite loop or being told mult is not a function.

What you here constructed is a predicate. A predicate is not the same as a function in computer science, you can not write A is B + some_pred(C), or at least not as far as I know in ISO Prolog, and definitely not without adding some extra logic.
In order to pass values, one uses variables. We can thus call the mult/3 predicate recursively, and use a variable that will be unified with the result. We can then perform arithmetic with it, like:
mult(0, _, 0).
mult(X, Y, Z) :-
X1 is X - 1,
mult(X1, Y, Z1),
Z is Y + Z1.
Note that you can not reassign a (different) value to a variable. So if, like you did in the question, use Z twice, then given Y is not 0, this will fail.
The above is however still not sufficient, since it will produce a result, but then get stuck in an infinite loop since if it calls (eventually) mult(0, 4, Z) (4 is here just a value), there are two ways to resolve this: with the base case, and with the recursive case.
We thus need a "guard" for the second case, like:
mult(0, _, 0).
mult(X, Y, Z) :-
X > 0,
X1 is X - 1,
mult(X1, Y, Z1),
Z is Y + Z1.
We then obtain for example:
?- mult(14, 25, Z).
Z = 350 ;
false.
One can improve the speed of this mult/3 predicate by implementing a version with an accumulator. I leave this as an exercise.

Related

Using dot-product instead of multiplying with transpose

We have the following equation, that we want to implement into our code with arrays/matrices
h(x, y, z) = ax + by + cz
pseudeo code:
X = [a, b, c]
A = [x, y, z]
Often I see the equation being implemented like this:
h = transpose(A) * T
Is there any difference of just using the dot product?
h = dotproduct(A, X)
Is there a specific reason why the transpose is used over the dotproduct?
Mathematically, there's no difference. In implementation- dotproduct(...) may actually be faster, since transpose(...) may eagerly move the elements around prior to the matrix multiplication, doing "unnecessary" work.

F# recursive function that takes single point and index

How do you write a F# recursive function 'something' that takes a single point (x, y) and index i as
an arguments and returns an ๐‘–๐‘กโ„Ž element of the infinite list corresponding to S(x, y).
ex: let something (x,y) i =
F# function F(๐‘ฅ,๐‘ฆ) should be defined as:
F(x,y)(u, v) = (u2 โˆ’ v2 + x, 2uv + y)
F# function 'something' ๐‘‚(x, y) of a point (x, y) should be an infinite list of items:
S(x, y) = {(0, 0), F(x,y)(0, 0), F(๐‘ฅ,y)(F(x,y)(0, 0)), F(x,y)(F(x,y)(F(x,y)(0, 0))), โ€ฆ}
This looks like an assignment to me. I don't mind helping out but at the same time I don't want to give the full solution.
The exercise itself looks like generating the series:
Z' = Z*Z + C
For a complex number Z and C. This is commonly done when generating the mandelbrot or julia set.
The function F can be written almost like the definition in F#:
let f (x, y) (u, v) = (u*u - v*v + x, 2.*u*v + y)
The infinite set S is generated from a starting point (0,0) and applying the output of f on itself over and over again.
An infinite set in F# can be represented using seq and you can create them using seq comprehesions
Once you have an infinite seq with the right values you can pick the ith value by using Seq.item

Problem with simple recursion task in Prolog

I'm currently solving some problems in prolog and I can't seem to get it work with one question regarding recursion, I have been presented with this table: Gryffindor Table.
Given that information, I made my own KB with this content:
/*
This order represents how they are sit from left to right
parvati_patil is left to lavender_brown,
lavender_brown is left to neville_longbottom
and so on, until we reach parvati again at the end.
*/
seatedTogether(parvati_patil, lavender_brown).
seatedTogether(lavender_brown, neville_longbottom).
seatedTogether(neville_longbottom, alicia_spinnet).
seatedTogether(alicia_spinnet, fred_weasley).
seatedTogether(fred_weasley, george_weasley).
seatedTogether(george_weasley, lee_jordan).
seatedTogether(lee_jordan, dennis_creevey).
seatedTogether(dennis_creevey, dean_thomas).
seatedTogether(dean_thomas, ginny_weasley).
seatedTogether(ginny_weasley, angelina_johnson).
seatedTogether(angelina_johnson, seamus_finnigan).
seatedTogether(seamus_finnigan, colin_creevey).
seatedTogether(colin_creevey, harry_potter).
seatedTogether(harry_potter, hermione_granger).
seatedTogether(hermione_granger, ron_weasley).
seatedTogether(ron_weasley, natalie_mcdonald).
seatedTogether(natalie_mcdonald, katie_bell).
seatedTogether(katie_bell, parvati_patil).
% X is left to Y if they are seatedTogether(X,Y)
isAtLeft(X,Y):-seatedTogether(X,Y).
% X is right to Y if they are seatedTogether(Y,X)
isAtRight(X,Y):-seatedTogether(Y,X).
/*
This rule just tells us who X is two places away from Y,
X is two places away from Y if
X is seatedTogether(X,Z)
and that Z is seatedTogether(Z,Y).
*/
twoPlacesAway(X,Y):-seatedTogether(X, Z), seatedTogether(Z,Y).
/*
This rule just tells us whos sitting # the table
by just unifying X with the values of seatedTogether(X,Y)
without regarding Y.
*/
atTable(X):-seatedTogether(X,_).
/*
Between two:
Its supposed to tell us whos Z is between X and Y
The perfect case (for me) would be that X and Y are sitting
together, so they have no one in the middle.
The other way around would be that
X is not equal to Y
X1 is sitting left to X,
and then we call it again with
X1, Y and Z1 as args,
after each call, we equal
Z to X1 value.
*/
betweenTwo(X,Y,Z):-isAtLeft(X,Y),isAtRight(Y,X).
betweenTwo(X,Y,Z):-
X \= Y,
isAtLeft(X, X1),
betweenTwo(X1, Y, Z1),
Z = X1.
The problem comes with the last rule definition, if I call it like this:
betweenTwo(ron_weasley, alicia_spinnet, Z).
The value of Z should be:
natalie_mcdonald,
katie_bell,
parvati_patil,
lavender_brown,
neville_longbottom.
But Z only unifies with the value of
natalie_mcdonald.
I believe I'm super close to it, but I'm really lost on what's going wrong with that rule. I defined it so X step by step equals the value of Y, but with the value before Y it should fall in the perfect case and stop moving, and unify the rest of elements before it. Any ideas?
First: your base case (what you call "perfect case") says "if X is at left of Y, and Y is at right of X, then every Z is between them", instead of "no one is between them" (the conditions are redundant as well). The base case should say when the predicate holds (that is, when some Z is between X and Y), not when it doesn't. See also this answer: https://stackoverflow.com/a/3001941/9204
Second: in the non-base case, you have
isAtLeft(X, X1),
betweenTwo(X1, Y, Z1),
Z = X1.
When Prolog searches for X1 in isAtLeft(ron_weasley, X1), the only answer is natalie_mcdonald, and later Z = X1 forces Z to be natalie_mcdonald too.
So this part of your code is equivalent to
isAtLeft(X, Z),
betweenTwo(Z, Y, Z1).
or in words "Z is between X and Y if: X is not equal to Y, X is directly to the left of Z, and some Z1 is between Z and Y", which doesn't make sense.
You should note the warning about singleton variable Z1, too.

ocaml vector space

I have a R3 space and I'm trying to figure some math "problems" with OCAML functions.
Define function "move", which moves plane based on the plane_name (ex. plane1) and vector (x, y, z):
example:
plane1 = [(1,2,-3); (10,5,2); (-2,3,7)]
move plane1 (1,2,-3);;
- : (int * int * int) list = [(2, 4, -6); (11, 7, -1); (-1, 5, 4)]
Thank you
I'll restrict my answer to problem 3.
I don't know where you're at with OCaml and what limitations have been imposed on your answer. (Forgive me, but I'm assuming this is a homework problem.) Let's assume the point of the exercise is to begin to think recursively. So then you want to write a function like this:
let move plane (x, y, z) = (( code goes here ))
For thinking recursively, the basic insight is that a plane is a list of points and you want to do the same thing to all the points. So a lower-level view of the function would be like this:
let rec move point_list (x, y, z) = (( code goes here ))
Now, a list is either empty, or it isn't. You just need to figure out what to do in each case. Furthermore, when the list is not empty you can use your own function recursively as long as you call it with a smaller list.
If, in fact, the point of this exercise is not to learn recursive thinking, then the answer would be completely different. In particular, there's a function in the List module that would make it pretty easy to solve the problem.
Update
Apparently you want to solve the problem non-recursively. To show how this would work, here is a function that takes two points and adds 1 to the x, y, and z coordinates of both points:
let add1 [(x1, y1, z1); (x2, y2, z2)] =
[(x1 + 1, y1 + 1, z1 + 1); (x2 + 1, y2 + 1, z2 + 1)]
This will cause a compiler warning because it fails for many possible inputs. In particular, it fails whenever the list has some number of points other than 2. To eliminate the warning, we need to decide what we want to return for those cases. Let's say we always return the list unchanged in those cases. Then we get the following:
let add1 = function
| [(x1, y1, z1); (x2, y2, z2)] ->
[(x1 + 1, y1 + 1, z1 + 1); (x2 + 1, y2 + 1, z2 + 1)]
| pts -> pts
I guess you know what you want, but this is not particularly idiomatic OCaml.
Another way to solve the problems non-recursively (without rec) would be to use functions from the List module. That would be much more idiomatic, and in fact is probably what I would do in a real-world situation.

How do I use mathematica to implicitly solve differential equations of a single variable?

I'm trying to force Mathematica to implicitly differentiate an ellipse equation of the form:
x^2/a^2+y^2/b^2 == 100
with a = 8 and b = 6.
The command I'm using looks like this:
D[x^2/a^2 + y^2/b^2 == 100/. y -> 3/4*Sqrt[6400-x^2], x]
where, y->3/4*Sqrt[6400-x^2] comes from solving y in terms of x.
I got this far by following the advice found here: http://www.hostsrv.com/webmaa/app1/MSP/webm1010/implicit
Input for this script is the conventional way that an implicit
relationship beween x and y is expressed in calculus textbooks. In
Mathematica you need to make this relationship explicit by using y[x]
in place of y. This is done automatically in the script by replacing
all occurances of y with y[x].
But the solution Mathematica gives does not have y' or dy/dx in it (like when I solved it by hand). So I don't think it's been solved correctly. Any idea on what command would get the program to solve an implicit differential? Thanks.
The conceptually easiest option (as you mentioned) is to make y a function of x and use the partial derivative operator D[]
In[1]:= D[x^2/a^2 + y[x]^2/b^2 == 100, x]
Solve[%, y'[x]]
Out[1]= (2 x)/a^2 + (2 y[x] y'[x])/b^2 == 0
Out[2]= {{y'[x] -> -((b^2 x)/(a^2 y[x]))}}
But for more complicated relations, it's best to use the total derivative operator Dt[]
In[3]:= SetOptions[Dt, Constants -> {a, b}];
In[4]:= Dt[x^2/a^2 + y^2/b^2 == 100, x]
Solve[%, Dt[y, x]]
Out[4]= (2 x)/a^2 + (2 y Dt[y, x, Constants -> {a, b}])/b^2 == 0
Out[5]= {{Dt[y, x, Constants -> {a, b}] -> -((b^2 x)/(a^2 y))}}
Note that it might be neater to use SetAttributes[{a, b}, Constant] instead of the SetOptions[Dt, Constants -> {a, b}] command... Then the Dt doesn't carry around all that extra junk.
The final option (that you also mentioned) is to solve the original equation for y[x], although this is not always possible...
In[6]:= rep = Solve[x^2/a^2 + y^2/b^2 == 100, y]
Out[6]= {{y -> -((b Sqrt[100 a^2 - x^2])/a)}, {y -> (b Sqrt[100 a^2 - x^2])/a}}
And you can check that it satisfies the differential equation we derived above for both solutions
In[7]:= D[y /. rep[[1]], x] == -((b^2 x)/(a^2 y)) /. rep[[1]]
Out[7]= True
You can substitute your values a = 8 and b = 6 anytime with replacement rule {a->8, b->6}.
If you actually solve your differential equation y'[x] == -((b^2 x)/(a^2 y[x]) using DSolve with the correct initial condition (derived from the original ellipse equation) then you'll recover the solution for y in terms of x given above.

Resources