Related
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]
I'm writing a function in R that needs to solve the basic quadratic equation and gives you the roots. I need to print out imaginary numbers if applicable. Below is my code. Could anyone give me advice on how I could improve my coding?
quad = function(a, b, c){
D = b^2 - 4*a*c
if (D < 0){
cat("The roots are", x, "and", y,"i\n");
z < - complex(real = x, imaginary = y)
return();
}
x = (-b - D^0.5)/(2*a)
y = (-b + D^0.5)/(2*a)
cat("The two roots are", x, "and", y, "\n");
}
Just keep in mind I'm an incredibly new R programmer, and I am aware this is an incredibly simple code. Any advice would be greatly appreciated.
In the line : cat("The roots are", x, "and", y,"i\n"); it will search for x and y which are not declared. Also it will calculate the roots even if D<0 so better you use if, else block like:
if (D < 0){
# cat("The roots are", x, "and", y,"i\n");
# z < - complex(real = x, imaginary = y)
cat("imaginary roots")
}
else{
x = (-b - D^0.5)/(2*a)
y = (-b + D^0.5)/(2*a)
cat("The two roots are", x, "and", y, "\n");
}
You can use this simple code.
quadr=function(a,b,c){
D=b^2-4*a*c
m=ifelse(D<0,complex(1,0,sqrt(abs(k))),sqrt(k))
c((-b+m)/(2*a),(-b-m)/(2*a))
}
quadr(1,1,6)
[1] -0.5+2.397916i -0.5-2.397916i
quadr(1,1,-6)
[1] 2 -3
I am trying to define a family tree and the relationships between its nodes basing their definitions on three predicates: male/1, female/1 and parent_of/2.
I have defined the notions of ascendant, descendant, father, mother, son, daughter, grandfather, grandmother, aunt, uncle and cousin. Any new definition can't be based on the notion of "brother/sister of", but only on the previous ones.
This is the code:
male(daniel).
male(miguelangel).
male(mario).
male(mahmoud).
male(esteban).
male(enrique).
male(javier).
male(miguelin).
female(diana).
female(hengameh).
female(vicenta).
female(mahvash).
female(angeles).
female(mexicana).
female(eloina).
female(esmeralda).
female(cristina).
female(otilia).
parent_of(miguelangel, daniel).
parent_of(miguelangel, diana).
parent_of(hengameh, daniel).
parent_of(hengameh, diana).
parent_of(mario, miguelangel).
parent_of(mario, esteban).
parent_of(mario, eloina).
parent_of(mario, angeles).
parent_of(mario, otilia).
parent_of(vicenta, miguel).
parent_of(vicenta, esteban).
parent_of(vicenta, eloina).
parent_of(vicenta, angeles).
parent_of(vicenta, otilia).
parent_of(mahmoud, hengameh).
parent_of(mahvash, hengameh).
parent_of(enrique, javier).
parent_of(angeles, javier).
parent_of(cristina, miguelin).
parent_of(otilia, cristina).
parent_of(eloina, esmeralda).
% Rules
ancestor(X, Y) :-
parent_of(X, Y);
parent_of(X, Z),
ancestor(Z, Y).
descendant(X, Y) :-
ancestor(Y, X).
father(X, Y) :-
parent_of(X, Y),
male(X).
mother(X, Y) :-
parent_of(X, Y),
female(X).
son(X, Y) :-
parent_of(Y, X),
male(X).
daughter(X, Y) :-
parent_of(Y, X),
female(X).
grandfather(X, Y) :-
parent_of(X, Z),
parent_of(Z, Y),
male(X).
grandmother(X, Y) :-
parent_of(X, Z),
parent_of(Z, Y),
female(X).
aunt(X, Y) :-
(grandfather(Z, Y) ; grandmother(Z, Y)),
(father(Z, X) ; mother(Z, X)),
not(parent_of(X, Y)),
female(X).
uncle(X, Y) :-
(grandfather(Z, Y) ; grandmother(Z, Y)),
(father(Z, X) ; mother(Z, X)),
not(parent_of(X, Y)),
male(X).
cousin(X, Y) :-
((uncle(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P)));
((aunt(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P))).
For the sake of clarity I have represented through an image the part of the tree where I'm having issues:
When I write
cousin(X, Y) :-
((uncle(Z, Y), parent_of(Z, X)));
((aunt(Z, Y), parent_of(Z, X))).
instead of
cousin(X, Y) :-
((uncle(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P)));
((aunt(Z, Y), parent_of(Z, X)) ; (cousin(P, Y), descendant(X, P))).
I get
?- cousin(miguelin, daniel).
false.
?- cousin(cristina, daniel).
true .
which are valid results. But when I introduce the recursive definitions on the right, as stated on the first (big) code, for saying that the descendants of the cousins of Y are also the cousins of Y, the program crashes:
?- cousin(miguelin, daniel).
ERROR: Out of local stack
I don't understand why. If I look at the image, it makes sense (at least to me) that recursive definition, and miguelin should be now the cousin of daniel (since he is a descendant of another cousin of daniel, which is cristina). I also tested it "manually" and I got the right result:
?- cousin(cristina, daniel), descendant(X, cristina).
X = miguelin ;
What's wrong with the definition?
One problem with the cousin/2 predicate is that the recursion is occurring before you resolve the descendant/2, and cousin/2 is having an infinite recursion issue in this context. As a simple way to fix that, you can swap them around. Also, you have one redundant recursive subclause. So the modified cousin/2 predicate would be:
cousin(X, Y) :-
(uncle(Z,Y), parent_of(Z,X)) ;
(aunt(W,Y), parent_of(W,X)) ;
(descendant(X,P), cousin(P,Y)).
And then you get:
?- cousin(miguelin, daniel).
true ;
false.
?- cousin(cristina, daniel).
true ;
false.
?-
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.
I'm trying to write a function in SML to compute the partial sum of an alternating harmonic series, and for the life of me I can't figure out why the compiler says one of the cases is redundant. I haven't used case statements before(or local, for that matter), but the order of these cases seems right to me.
local
fun altHarmAux (x:int, y:real) =
case x of
1 => 1.0
| evenP => altHarmAux(x-1, y - y/(real x))
| oddP => altHarmAux(x-1, y + y/(real x))
in
fun altHarmonic (a:int) = altHarmAux(a, real a)
end
Even if you have defined the two predicate functions somewhere, they can't be used in a case like that.
whatever you write on the left hand of => will be bound to the value you are matching on, thus the two last matches in your case will match the same input, rendering the last one useless, as the first one will always be used
You will have to apply your predicate function to the value directly, and then match on the result
local
fun altHarmAux (x, y) =
case (x, evenP x) of
(1, _) => 1.0
| (_ true) => altHarmAux(x-1, y - y/(real x))
| (_, false) => altHarmAux(x-1, y + y/(real x))
in
fun altHarmonic a = altHarmAux(a, real a)
end
or perhaps simpler
local
fun altHarmAux (1, _) = 1.0
| altHarmAux (x, y) =
altHarmAux (x-1, y + (if evenP x then ~y else y) / (real x))
in
fun altHarmonic a = altHarmAux (a, real a)
end
or
local
fun altHarmAux (1, _) = 1.0
| altHarmAux (x, y) =
if evenP x then
altHarmAux (x-1, y - y/(real x))
else
altHarmAux (x-1, y + y/(real x))
in
fun altHarmonic a = altHarmAux (a, real a)
end