How implement tarai in guile - guile

I now would like to run tarai, which reads in Prolog as follows. A test case would be to run ?- tarai(12,6,0,X). This is quite a hard test case, for example GNU Prolog crashes with this test case.
tarai(X, Y, Z, R) :-
X > Y ->
X1 is max(0,X-1), tarai(X1, Y, Z, Rx),
Y1 is max(0,Y-1), tarai(Y1, Z, X, Ry),
Z1 is max(0,Z-1), tarai(Z1, X, Y, Rz),
tarai(Rx, Ry, Rz, R);
R = Y.
I am mostly interested whether the test case can be run over a fully declarative version of some miniKanren code for tarai. Optionally I would be interested in running some test cases backwards.
I am a little bit at loss. I managed to install guile, a scheme variant, and can run the miniKanren test cases successfully. But miniKanren has no integer numbers, so what could be done?

Note that this algorithm only has one solution if it's exists and is deterministic. You may pass scheme variables as x,y,z directly to the kanren tarai function, there is no unification for those hence implementing the logic for X,Y,Z can be done without kanren variables. The R values however needs to be logic variables and you need to get the bounded values in the tarai(Rx,Ry,Rz,R) form e.g. lookup the value of Rx,Ry,Rz and feed those into the tarai function. Also you need to make sure that this form is executed after the first three forms has finished (which is easy to do because there is no pure multiple choices) so that you know that Rx,Ry,Rz is bounded. Also note that this algorithm might depend on execution order in order to be executed efficiently but again the determinism means that this point is straightforward to satisfy. Note that A -> B ; C translates here simply to schemes (if A B C) because A = X > Y is deterministic. So the code could look something like this in pseudocode
(define (tarai x y z r)
(lambda ()
(fresh (rx ry rz)
(if (> x y)
(conda
( (conda ((tarai (- x 1) y z rx)
(tarai (- y 1) z x ry)
(tarai (- z 1) x y rz)))
(project (rx ry rz) (tarai rx ry rz r))))
(== r y)))))

To do the deterministic verison in guile-log scheme macro interface see links on this site you can implement it with memoization as (without memoization the solution blows the variable stack on guile-log)
(define tarai
(memo
(<lambda> (x y z r)
(if (> x y)
(<var> (rx ry rz)
(<and>
(tarai (max (- x 1) 0) y z rx)
(tarai (max (- y 1) 0) z x ry)
(tarai (max (- z 1) 0) x y rz)
(tarai (<lookup> rx) (<lookup> ry) (<lookup> rz) r)))
(<=> r y)))))
scheme#(guile-user)> ,time (<run> 1 (r) (tarai 12 6 0 r))
$13 = (12)
;; 0.293411s real time, 0.290711s run time. 0.000000s spent in GC.
scheme#(guile-user)>

I tried running for example tarai(12,X,0,12) with clpfd, but it's to complex for it. And memoizing does not work with attributed variables for swipl. So the best solution atm that I can find is to use the deterministic memoized tarai with something like
tarai2(X,Y,Z,W) :-
(var(X)->between(0,20,X);true),
(var(Y)->between(0,20,Y);true),
(var(z)->between(0,20,Z);true),
tarai(X,Y,Z,W).
then all solutions Y,Z in that range with tarai2(12,Y,Z,12) can easilly be found.

The question was refrased to ask for how to implement a more general version of the tarai function in the prolog spec that allows variables in x,y,z fields. The technique here can be implemented in prolog with e.g. clpfd finite domain solver and something similar is needed for kanren (se comment discussions above e.g. the reference to numbers.scm). The key thing is to nuke -> and use guards for all cases and we will assume that operators >o =o <=o is all defined for variables (e.g. for var X, X > 0 will constrain X to be values 1,2,3,...). Also we will asume that '-o' is defined for variables as well of this kind using interval arithmetics constraints via a special 'iso'. Using this we can define tarai as the code below (this can be simplified if max and min is also defined as constraints but here we implement those via inequalities and a dived of cases in stead).
(define (taray x y z w)
(lambda ()
(conde ((<o x y)
(fresh (rx ry rz)
(conde
((conde
((>o x 0)
(fresh (xx)
(conde
((iso xx (-o x 1))
(tarai xx y z rx)))))
((== x 0) (tarai 0 y z rx)))
(conde
((>o y 0)
(fresh (yy)
(conde
((iso yy (-o y 1))
(tarai yy z x ry)))))
((== y 0) (tarai 0 z x ry)))
(conde
((>o z 0)
(fresh (zz)
(conde
((iso zz (-o z 1))
(tarai zz x y rz)))))
((== z 0) (tarai 0 x y r<)))
(tarai rx ry rz r)))))
((>=o x y) (== x y))))))

I'm the developer of guile-log a logic programming environment on guile scheme that has both minikanren constructs and prolog constructs and one can mix them. It also has a clpfd library ported so here you can do the following (unfourtunately atm it does not work (a bug i'm working on)). Assume that clpfd is imported. (,, ;; is interleaving kanren like ops). Replacing ,, with , and ;; with ; you get code that can run on for example swi prolog using the clpfd library.
tarai(X,Y,Z,W) :-
(
X #> Y ,
(
(
((X #> 0 , XX #= X - 1, tarai(XX,Y,Z,RX)) ;;
(X = 0 , tarai(0,Y,Z,RX))) ,,
((Y #> 0 , YY #= Y - 1, tarai(YY,Z,X,RY)) ;;
(Y = 0 , tarai(0,Z,X,RY))) ,,
((Z #> 0 , ZZ #= Z - 1, tarai(ZZ,X,Y,RZ)) ;;
(Z = 0 , tarai(0,X,Y,RZ)))
) ,,
tarai(RX,TY,RZ,R)
)
) ;;
(X #=< Y, R=Y).

This is a slow implementation that is declarative and uses numbers.scm (as suggested by the author of the question) and minkanren.
(load "minkanren.scm)
(load "numbers.scm")
(define one (build-num 1))
(define zero (build-num 0))
(define (tarai x y z r)
(conde
((<=o x y) (== r y))
((<o y x)
(fresh (rx ry rz)
(conde
((fresh (xx)
(conde
((<o zero x) (minuso x one xx) (tarai xx y z rx))
((== zero x) (tarai zero y z rx))))
(fresh (yy)
(conde
((<o zero y) (minuso y one yy) (tarai yy z x ry))
((== zero y) (tarai zero z x ry))))
(fresh (zz)
(conde
((<o zero z) (minuso z one zz) (tarai zz x y rz))
((== zero z) (tarai zero x y rz))))
(tarai rx ry rz r)))))))
If the derivation direction is reversed (so wee add numbers) we can still solve due to the declarative style,
tarai(4,2,Z,4):, (you need to make binaries of the number) will lead to
Y = [0, 1],
W = [0, 0, 1],
Z = [0, 0, 1],
X = [0, 0, 1].
And supposedly if tabling is added:
tarai(12,6,0,W):
Z = (),
X = [0, 0, 1, 1],
Y = [0, 1, 1],
W = [0, 0, 1, 1].

Related

Symply.py for getting coefficients for ALL combination of the variables of a multivariable polynomial

How to get coefficients for ALL combinations of the variables of a multivariable polynomial using sympy.jl or another Julia package for symbolic computation?
Here is an example from MATLAB,
syms a b y
[cxy, txy] = coeffs(ax^2 + by, [y x], ‘All’)
cxy =
[ 0, 0, b]
[ a, 0, 0]
txy =
[ x^2y, xy, y]
[ x^2, x, 1]
My goal is to get
[ x^2y, xy, y]
[ x^2, x, 1]
instead of [x^2, y]
I asked the same question at
https://github.com/JuliaPy/SymPy.jl/issues/482
and
https://discourse.julialang.org/t/symply-jl-for-getting-coefficients-for-all-combination-of-the-variables-of-a-multivariable-polynomial/89091
but I think I should ask if this can be done using Sympy.py.
Using Julia, I tried the following,
julia> #syms x, y, a, b
julia> ff = sympy.Poly(ax^2 + by, (x,y))
Poly(ax**2 + by, x, y, domain='ZZ[a,b]')
julia> [prod(ff.gens.^i) for i in ff.monoms()]
2-element Vector{Sym}:
x^2
y
This is a longer form rewrite of the one-liner in the comment.
It uses Pipe.jl to write expressions 'functionally', so familiarity with pipe operator (|>) and Pipe.jl will help.
using SymPy
using Pipe
#syms x, y, a, b
ff = sympy.Poly(a*x^2 + b*y, (x,y))
max_degrees =
#pipe ff.monoms() .|> collect |> hcat(_...) |>
reduce(max, _, dims=2) |> vec
degree_iter =
#pipe max_degrees .|> UnitRange(0, _) |>
tuple(_...) |> CartesianIndices
result = [prod(ff.gens.^Tuple(I)) for I in degree_iter] |>
reverse |> eachcol |> collect
or using more of the python methods:
[prod(ff.gens.^I) for
I in Iterators.product((0:d for d in ff.degree.(ff.gens))...)] |>
reverse |> eachcol |> collect
Both give the desired result:
2-element Vector{...}:
[x^2*y, x*y, y]
[x^2, x, 1]
UPDATE:
In case there are more than 2 generators, the result needs to be a Array with higher dimension. The last bits of matrix transposes is immaterial and the expressions become:
Method 1:
max_degrees =
#pipe ff.monoms() .|> collect |> hcat(_...) |>
reduce(max, _, dims=2) |> vec
degree_iter =
#pipe max_degrees .|> UnitRange(0, _) |>
tuple(_...) |> CartesianIndices
result = [prod(ff.gens.^Tuple(I)) for I in degree_iter]
Method 2:
result = [prod(ff.gens.^Tuple(I)) for I in degree_iter]
Thanks a lot #Dan Getz. Your solution works for the TOY example from MATLAB. My real case is more complicated, which has more variables and polynominals. I tried your method for 3 variables,
using SymPy
#syms x, y, z, a, b
ff = sympy.Poly(a*x^2 + b*y + z^2 + x*y + y*z, (x, y, z))
[prod(ff.gens.^Tuple(I)) for I in CartesianIndices(tuple(UnitRange.(0,vec(reduce(max, hcat(collect.(ff.monoms())...), dims=1)))...))]
I got the following error,
ERROR: LoadError: DimensionMismatch: arrays could not be broadcast to a common size; got a dimension with lengths 3 and 5
Stacktrace:
How to generate your method to any number of variables with different degrees, e.g., x^3 + y^3 + z^3 + xyz + xy^2z?
You can find the degree of each of the two variables of interest and then use them to create the matrix of generators; you can use them to get the coefficients of interest. I am not sure what you expect if the equation were like a*x**2 + b*y + c...
>>> from sympy import *
>>> from sympy.abc import a, b, x, y
>>> eq = a*x**2 + b*y
>>> deg = lambda x: Poly(eq, x).degree() # helper to give degree in "x"
>>> v = (Matrix([x**i for i in range(deg(x),-1,-1)]
... )*Matrix([y**i for i in range(deg(y),-1,-1)]).T).T; v
Matrix([[x**2*y, x*y, y], [x**2, x, 1]])
>>> Matrix(*v.shape, [eq.coeff(i) if i.free_symbols else eq.as_coeff_Add()[0]
... for i in v])
Matrix([[0, 0, b], [a, 0, 0]])
From #jverzani (thanks)
using SymPy;
#syms a b x y;
eq = a*x^2 + b*y;
deg = x -> sympy.Poly(eq, x).degree();
xs, ys = [x^i for i ∈ range(deg(x):-1:0], [y^i for i ∈ deg(y):-1:0];
v = permutedims(xs .* permutedims(ys));
M = [x^2*y x*y y; x^2 x 1];
[length(free_symbols(i)) > 0 ? eq.coeff(i) : eq.as_coeff_add()[1] for i ∈ v];
[0 0 b; a 0 0]

Euclid in Prolog (greatest common denominator)

We've been given a pseudo-code that we are supposed to translate into Prolog:
This is the solution I've been able to come up with:
% if y = 0: return x
test(X, 0, Output) :- Output is X.
% if x = 0: return y
test(0, Y, Output) :- Output is Y.
% if if x > y: return euclid_recursive(x - y, y)
test(X,Y,Output) :-
% if x > y: return euclid_recursive(x - y, y)
( X > Y -> Temp is X - Y ,
test(Temp, Y,Output);
% return euclid_recursive(x, y - x)
Temp is Y - X,
test(X, Temp, Output)
).
I've tested it with a few examples and it seems to work. I would appreciate it if you folks could have another look at it though.
You only need to use is/2 [swi-doc] to evaluate a numerical expression. So here you can use unification:
test(X, 0, X).
test(0, X, X).
test(X, Y, Output) :-
( X > Y
-> Temp is X - Y,
test(Temp, Y,Output)
; Temp is Y - X,
test(X, Temp, Output)
).
Another major problem is that Prolog will keep making recursive calls, even if one of the elements is zero. It will thus keep proposing new solutions:
?- test(36, 63, R).
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
R = 9 ;
…
This may not seem like a (major) problem, but if you use test/3 as part of another program, it can get stuck in an infinite loop where test/3 keeps proposing R = 9, and the next predicate call each time rejecting this.
test(X, 0, X).
test(0, X, X) :-
X > 0.
test(X, Y, Output) :-
X > 0,
Y > 0,
( X > Y
-> Temp is X - Y,
test(Temp, Y,Output)
; Temp is Y - X,
test(X, Temp, Output)
).
This will only propose one solution:
?- test(36, 63, R).
R = 9 ;
false.

"Syntax error" while writing OCaml function?

I am writing a function in OCaml to raise x to the power of y.
My code is:
#let rec pow x y =
if y == 0 then 1 else
if (y mod 2 = 0) then pow x y/2 * pow x y/2 else
x * pow x y/2 * pow x y/2;;
When I try to execute it, I get an error for syntax in line one, but it doesn't tell me what it is.
When you wrote the code, did you type the #? The # is just a character that the OCaml REPL outputs to prompt for input; it is not part of the code. You should not type it.
Here are some other errors that you should fix:
== is physical equality in OCaml. = is structural equality. Although both work the same for unboxed types (such as int), it's better practice to do y = 0. Note that you use =, the recommended equality, in the expression y mod 2 = 0.
You need parentheses around y/2. pow x y/2 parses as (pow x y) / 2, but you want pow x (y / 2).

Prolog:: f(x) recursion

I'm a beginner to Prolog and have two requirements:
f(1) = 1
f(x) = 5x + x^2 + f(x - 1)
rules:
f(1,1).
f(X,Y) :-
Y is 5 * X + X * X + f(X-1,Y).
query:
f(4,X).
Output:
ERROR: is/2: Arguments are not sufficiently instantiated
How can I add value of f(X-1)?
This can be easily solved by using auxiliary variables.
For example, consider:
f(1, 1).
f(X, Y) :-
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
This is a straight-forward translation of the rules you give, using auxiliary variables T1 and T2 which stand for the partial expressions f(X-1) and X-1, respectively. As #BallpointBen correctly notes, it is not sufficient to use the terms themselves, because these terms are different from their arithmetic evaluation. In particular, -(2,1) is not the integer 1, but 2 - 1 #= 1 does hold!
Depending on your Prolog system, you may ned to currently still import a library to use the predicate (#=)/2, which expresses equality of integer expressesions.
Your example query now already yields a solution:
?- f(4, X).
X = 75 .
Note that the predicate does not terminate universally in this case:
?- f(4, X), false.
nontermination
We can easily make it so with an additional constraint:
f(1, 1).
f(X, Y) :-
X #> 1,
Y #= 5*X + X^2 + T1,
T2 #= X - 1,
f(T2, T1).
Now we have:
?- f(4, X).
X = 75 ;
false.
Note that we can use this as a true relation, also in the most general case:
?- f(X, Y).
X = Y, Y = 1 ;
X = 2,
Y = 15 ;
X = 3,
Y = 39 ;
X = 4,
Y = 75 ;
etc.
Versions based on lower-level arithmetic typically only cover a very limited subset of instances of such queries. I therefore recommend that you use (#=)/2 instead of (is)/2. Especially for beginners, using (is)/2 is too hard to understand. Take the many related questions filed under instantiation-error as evidence, and see clpfd for declarative solutions.
The issue is that you are trying to evaluate f(X-1,Y) as if it were a number, but of course it is a predicate that may be true or false. After some tinkering, I found this solution:
f(1,1).
f(X,Y) :- X > 0, Z is X-1, f(Z,N), Y is 5*X + X*X + N.
The trick is to let it find its way down to f(1,N) first, without evaluating anything; then let the results bubble back up by satisfying Y is 5*X + X*X + N. In Prolog, order matters for its search. It needs to satisfy f(Z,N) in order to have a value of N for the statement Y is 5*X + X*X + N.
Also, note the condition X > 0 to avoid infinite recursion.

Sage's (or Maxima's) solve gives a bad answer for diff(p, x) == 0?

I am using Sage to (within a script) solve a simple equation in two variables:
sage: x, y = var("x y")
sage: p = x*y + x/y + 1/x
sage: diff(p, x)
y + 1/y - 1/x^2
sage: diff(p, y)
x - x/y^2
sage: solve([diff(p,x)==0, diff(p,y)==0], [x,y])
[[x == 0, y == 0], [x == -1/2*sqrt(2), y == 1],
[x == 1/2*sqrt(2), y == 1], [x == -1/2*I*sqrt(2), y == -1],
[x == 1/2*I*sqrt(2), y == -1]]
For some reason, Sage returns a solution that isn't a solution at all, here [x == 0, y == 0] can easily be seen NOT to be an answer of [y + 1/y - 1/x^2 == 0, x - x/y^2 == 0].
Is this a bug? a known bug? or am I doing something wrong?
UPDATE: rephrased the title, and I am wondering, worst case, how can I substitute the solutions back in the system to manually check if the equations are verified?
PS: I would post this on AskSage, but it is currently down.
Well, looks like Maxima's solve function is returning the spurious solution [x = 0, y = 0]. I see that Maxima's to_poly_solve is better behaved here.
p : x*y + x/y + 1/x;
load (to_poly_solve);
[dpx, dpy] : [diff (p, x), diff (p, y)];
to_poly_solve ([dpx, dpy], [x, y]);
=> %union([x = -1/sqrt(2),y = 1],[x = 1/sqrt(2),y = 1],
[x = -%i/sqrt(2),y = -1],[x = %i/sqrt(2),y = -1])
for xy in args (%) do print (subst (xy, [dpx, dpy]));
=>
[0,0]
[0,0]
[0,0]
[0,0]
I don't know how to call to_poly_solve from Sage, although I'm pretty sure it's possible.
Hope this helps. Good luck & have fun.

Resources