Custom simplification (rules and patterns) - maxima

Hello I'm very new to maxima.
How could I have something like dot products noticed and simplfied?
Attempt 1:
tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));
Works for a[1]*b[1]+a[2]*b[2] but not v[1]*w[1]+v[2]*w[2] nor w[2]*v[2]+123+v[1]*w[1].
Attempt 2:
matchdeclare(a, lambda([x], length(x)=2));
matchdeclare(b, lambda([x], length(x)=2));
tellsimpafter(a[1]*b[1]+a[2]*b[2], dot(a,b));
Doesn't even work for a[1]*b[1]+a[2]*b[2].

Here's a possible solution. Assuming that you know the names of the arrays, it's straightforward to extract the inner product. Then loop over that with all possible array names, as determined by looking at the subscripted variables in the expression.
/* solution for https://stackoverflow.com/questions/69673365/custom-simplification-rules */
/* try all combinations of potential arrays in succession */
contract_inner_products (e) :=
(for S in powerset (subscripted_variables(e), 2)
do block ([%xx: first(S), %yy: second(S)],
e: apply1 (e, rule_contract_inner_product)),
e);
/* extract potential arrays */
subscripted_variables (e) :=
setify (map (op, sublist (listofvars(e), subvarp)));
/* contract inner product, assuming arrays have been identified */
matchdeclare (aa, lambda([e], freeof(%xx, e) or freeof(%yy, e)),
bb, lambda([e], freeof(%xx, e) and freeof(%yy, e)),
xx, lambda([e], e = %xx), yy, lambda([e], e = %yy));
defrule (rule_contract_inner_product, aa + bb*xx[1]*yy[1] + bb*xx[2]*yy[2], aa + bb*dot(xx, yy));
Here are some examples.
(%i3) dotgh: g[1]*h[1] + g[2]*h[2] $
(%i4) dotab: a[1]*b[1] + a[2]*b[2] $
(%i5) dotxy: x[1]*y[1] + x[2]*y[2] $
(%i6) contract_inner_products (dotgh);
(%o6) dot(g, h)
(%i7) contract_inner_products (dotgh + dotxy);
(%o7) dot(x, y) + dot(g, h)
(%i8) contract_inner_products (dotgh - dotxy);
(%o8) dot(g, h) - dot(x, y)
(%i9) contract_inner_products (dotgh - 2*dotxy);
(%o9) dot(g, h) - 2 dot(x, y)
(%i10) contract_inner_products (n/2*dotgh - 2*dotxy);
dot(g, h) n
(%o10) ----------- - 2 dot(x, y)
2
(%i11) contract_inner_products (n/2*dotgh - 2*dotxy - 6*%pi^2);
dot(g, h) n 2
(%o11) (- 2 dot(x, y)) + ----------- - 6 %pi
2
It seems to work for stuff of the form dot(x, y) + dot(x, z).
(%i12) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2]);
(%o12) dot(g, h) + dot(f, g)
(%i13) contract_inner_products (dotgh + g[1]*f[1] + g[2]*f[2] + 123);
(%o13) dot(g, h) + dot(f, g) + 123
(%i14) contract_inner_products (dotgh + g[1]*x[1] + g[2]*x[2] + 123);
(%o14) dot(g, x) + dot(g, h) + 123
(%i15) contract_inner_products (dotgh + h[1]*x[1] + h[2]*x[2] + 123);
(%o15) dot(h, x) + dot(g, h) + 123
I didn't really expect it to work for dot(x, y) + dot(x, z), but anyway that's great.
If you try it on other examples, you'll probably find some cases which this approach doesn't recognize.
EDIT: Note that it's not necessary for the would-be dot product to be at the top level of the expression. It looks for potential inner products in subexpressions, too.
(%i11) 1/(1 - dotab/4);
1
(%o11) -----------------
a b + a b
2 2 1 1
1 - -------------
4
(%i12) contract_inner_products(%);
1
(%o12) -------------
dot(a, b)
1 - ---------
4
(%i13) expand (%o11);
1
(%o13) ---------------------
a b a b
2 2 1 1
(- -----) - ----- + 1
4 4
(%i14) contract_inner_products(%);
1
(%o14) -------------
dot(a, b)
1 - ---------
4

Related

Solving Equations with (wx)Maxima: Control stack exhausted

Solving Equations with (wx)Maxima: Control stack exhausted
I'm trying to solve equations with (wx)Maxima: formulate the equation, then let it insert the variables and solve the equation for the missing variable. But I'm having a hard time. Somehow it's having problems in the last line:
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.
That's my code:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
α: 30*%pi/180;
/*α: 30*°;*/
masse: 1000*kg;
g: 9.80665*m/(s*s);
b: 0.3*m;
B: 0.5*m;
L: 0.1*m;
F_g: masse*g;
F_H: masse * g;
kill(S, x);
S: solve(0=F_H-2*x*sin(α), x);
S: assoc(x, S);
kill(H, x);
H: solve(0=-F_g+2*x, x);
H: assoc(x, H);
kill(Ly, x);
Ly: solve(tan(α)=x/(B/2), x);
Ly: assoc(x, Ly);
kill(FN, x);
FN: solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x);
FN: assoc(x, FN);
If I calculate it "directly", it works though:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
kill(FN, x);
FN: solve([α=30*%pi/180, H=196133/40*N,
B=0.5*m, L=0.1*m,
Ly=sqrt(3)/12*m, S=196133/20*N,
0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly],
[x, α, H, B, L, Ly, S]);
FN: assoc(x, FN[1]);
FN: float(FN);
(FN) 1934473685/128529*N
Unfortunately the unit package has not been updated in some time. I'll suggest to use instead the package ezunits, in which dimensional quantities are represented with a back quote. To solve equations, try dimensionally which goes through some gyrations to help other functions with dimensional quantities, e.g. dimensionally (solve (...)). (Note that dimensionally isn't documented, I'm sorry for the shortcoming.)
I've modified your program a little to remove some unneeded stuff and also to use rational numbers instead of floats; Maxima is generally more comfortable with rationals and integers than with floats. Here is the program:
linel: 65 $
load(ezunits) $
α: 30*%pi/180;
masse: 1000`kg;
g: rationalize(9.80665)`m/(s*s);
b: 3/10`m;
B: 5/10`m;
L: 1/10`m;
F_g: masse*g;
F_H: masse * g;
S: dimensionally (solve(0=F_H-2*x*sin(α), x));
S: assoc(x, S);
Ly: dimensionally (solve(tan(α)=x/(B/2), x));
Ly: assoc(x, Ly);
FN: dimensionally (solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x));
FN: assoc(x, FN);
subst (x = S, F_H-2*x*sin(α));
subst (x = Ly, tan(α)=x/(B/2));
subst (x = FN, H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly);
ratsimp (expand (%));
and here is the output I get. Note that I substituted the solutions back into the equations to verify them. It looks like it worked as expected.
(%i2) linel:65
(%i3) load(ezunits)
(%i4) α:(30*%pi)/180
%pi
(%o4) ---
6
(%i5) masse:1000 ` kg
(%o5) 1000 ` kg
(%i6) g:rationalize(9.80665) ` m/(s*s)
5520653160719109 m
(%o6) ---------------- ` --
562949953421312 2
s
(%i7) b:3/10 ` m
3
(%o7) -- ` m
10
(%i8) B:5/10 ` m
1
(%o8) - ` m
2
(%i9) L:1/10 ` m
1
(%o9) -- ` m
10
(%i10) F_g:masse*g
690081645089888625 kg m
(%o10) ------------------ ` ----
70368744177664 2
s
(%i11) F_H:masse*g
690081645089888625 kg m
(%o11) ------------------ ` ----
70368744177664 2
s
(%i12) S:dimensionally(solve(0 = F_H-2*x*sin(α),x))
690081645089888625 kg m
(%o12) [x = ------------------ ` ----]
70368744177664 2
s
(%i13) S:assoc(x,S)
690081645089888625 kg m
(%o13) ------------------ ` ----
70368744177664 2
s
(%i14) Ly:dimensionally(solve(tan(α) = x/(B/2),x))
1
(%o14) [x = --------- ` m]
4 sqrt(3)
(%i15) Ly:assoc(x,Ly)
1
(%o15) --------- ` m
4 sqrt(3)
(%i16) FN:dimensionally(solve(0 = (H*B)/2-x*(L+Ly)
+(S*sin(α)*B)/2
+S*cos(α)*Ly,x))
1 1
(%o16) [x = (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)]
(%i17) FN:assoc(x,FN)
1 1
(%o17) (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)
(%i18) subst(x = S,F_H-2*x*sin(α))
kg m
(%o18) 0 ` ----
2
s
(%i19) subst(x = Ly,tan(α) = x/(B/2))
1 1
(%o19) ------- = -------
sqrt(3) sqrt(3)
(%i20) subst(x = FN,(H*B)/2-x*(L+Ly)+(S*sin(α)*B)/2+S*cos(α)*Ly)
1 1
(- ---------) - --
4 sqrt(3) 10 1
(%o20) ((----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2 H
+ 1150136075149814375 3 ` kg m) + -) ` m
4
2
690081645089888625 kg m
+ ------------------ ` -----
281474976710656 2
s
(%i21) ratsimp(expand(%))
2
kg m
(%o21) 0 ` -----
2
s
EDIT. About converting kg*m/s^2 to N, you can apply the double back quote operator. For example:
(%i25) F_g `` N
690081645089888625
(%o25) ------------------ ` N
70368744177664
By the way, to convert back to floats, you can apply float:
(%i26) float(%)
(%o26) 9806.649999999998 ` N
Converting FN to N is a little more involved, since it's a more complex expression, especially because of H which doesn't have units attached to it yet. Some inspection seems to show the units of H must be kg*m/s^2. I'll apply declare_units to say that's what are the units of H. Then I'll convert FN to N.
(%i27) declare_units(H,(kg*m)/s^2)
kg m
(%o27) ----
2
s
(%i28) FN `` N
351843720888320 sqrt(3) qty(H)
(%o28) (-----------------------------------------
140737488355328 sqrt(3) + 351843720888320
3/2
1150136075149814375 3
+ -----------------------------------------) ` N
140737488355328 sqrt(3) + 351843720888320
(%i29) float(%)
(%o29) (1.023174629940149 qty(H) + 10033.91548470256) ` N
The notation qty(H) represents the unspecified quantity of H. One could also just subst(H = 100 ` kg*m/s^2, FN) (or any quantity, not just 100) and go from there.

Why is Maxima failing to give a solution?

I have a function in Maxima I am differentiating then attempting to find the value at which this is zero. When I use solve(), however, I am not given a solution. Why is this, and how can I work around it?
(%i1) f(x):=(-5*(x^4+5*x^3-3*x))/(x^2+1);
(%o1) f(x):=((-5)*(x^4+5*x^3+(-3)*x))/(x^2+1)
(%i2) df(x):=''(diff(f(x), x));
(%o2) df(x):=(10*x*(x^4+5*x^3-3*x))/(x^2+1)^2-(5*(4*x^3+15*x^2-3))/(x^2+1)
(%i3) solve(df(x), x);
(%o3) [0=2*x^5+5*x^4+4*x^3+18*x^2-3]
The function solve is not too strong; there are many problems it can't solve. A stronger version is under development. In the meantime, try the add-on package to_poly_solve. Here's what I get:
(%i1) df(x) := (10*x*(x^4+5*x^3-3*x))/(x^2+1)^2-(5*(4*x^3+15*x^2-3))/(x^2+1) $
(%i2) load (to_poly_solve) $
(%i3) to_poly_solve (df(x), x);
(%o3) %union([x = - 2.872468527640942], [x = - 0.4194144025323134],
[x = 0.3836388367122223], [x = 0.2041221431132173 - 1.789901606296292 %i],
[x = 1.789901606296292 %i + 0.2041221431132173])
Something which is maybe a little surprising is that to_poly_solve has returned a numerical solution instead of exact or symbolic. Tracing allroots shows that to_poly_solve has constructed a quintic equation and punted it to allroots. Since the general quintic doesn't have a solution in terms of radicals, and even in special cases it's probably very messy, maybe it's most useful to have a numerical solution anyway.
Try plot2d(df(x), [x, -3, 1]) to visualize the real roots returned above.
You can try to find a numerical solution. I don't know why solve does not try this. Either you take the ouput of aolveor you do hte folölowing:
(%i1) f(x):=(-5*(x^4+5*x^3-3*x))/(x^2+1);
4 3
(- 5) (x + 5 x + (- 3) x)
(%o1) f(x) := ---------------------------
2
x + 1
(%i2) df(x):=''(diff(f(x), x));
4 3 3 2
10 x (x + 5 x - 3 x) 5 (4 x + 15 x - 3)
(%o2) df(x) := ---------------------- - --------------------
2 2 2
(x + 1) x + 1
Bring it to a common denominator and extract the numerator:
(%i3) xthru(df(x));
4 3 2 3 2
10 x (x + 5 x - 3 x) - 5 (x + 1) (4 x + 15 x - 3)
(%o3) ------------------------------------------------------
2 2
(x + 1)
(%i4) num(%);
4 3 2 3 2
(%o4) 10 x (x + 5 x - 3 x) - 5 (x + 1) (4 x + 15 x - 3)
use allsrootsto find the roots of a polynomial numerically
(%i5) allroots(%);
(%o5) [x = 0.3836388391066617, x = - 0.4194143906217701,
x = 1.789901606296292 %i + 0.2041221431132174,
x = 0.2041221431132174 - 1.789901606296292 %i, x = - 2.872468734711326]
skip the complex solutions
(%i6) sublist(%,lambda([t],imagpart(rhs(t))=0))
;
(%o6) [x = 0.3836388391066617, x = - 0.4194143906217701,
x = - 2.872468734711326]

Substitute variable in Maxima

newbie Maxima question
I have a transfer function in Maxima
E1 : y = K_i*s/(s^2 + w^2);
I'd like to have the closed-form of the equation affter applying the bilinear transform
E2 : s = (2/Ts*(z-1)/(z+1));
I would like to get the transfer function for z, by substituing s by equation E2. How should I proceed?
Regards
Note that subst can apply one or more substitutions stated as equations. In this case, try subst(E2, E1).
That will probably create a messy result -- you can simplify it somewhat by applying ratsimp to the result.
Here's what I get from that.
(%i2) E1 : y = K_i*s/(s^2 + w^2);
K_i s
(%o2) y = -------
2 2
w + s
(%i3) E2 : s = (2/Ts*(z-1)/(z+1));
2 (z - 1)
(%o3) s = ----------
Ts (z + 1)
(%i4) subst (E2, E1);
2 K_i (z - 1)
(%o4) y = ------------------------------
2
4 (z - 1) 2
Ts (z + 1) (------------ + w )
2 2
Ts (z + 1)
(%i5) ratsimp (%);
2
2 K_i Ts z - 2 K_i Ts
(%o5) y = -----------------------------------------------
2 2 2 2 2 2 2
(Ts w + 4) z + (2 Ts w - 8) z + Ts w + 4

How to simplify matrix in terms of an equation

I have an matrix in Maxima, let´s say (for simplification of the problem):
A: matrix([2*(a^2+b^2+c^2)])
But I know that:
a^2+b^2+c^2 = 1
How do I simplify that matrix in Maxima in terms of that equation, in order to obtain A = [2]?
I found the solution:
A: matrix([2*(a^2+b^2+c^2)]);
eq: a^2+b^2+c^2 = 1;
scsimp(A, eq);
You can use tellrat.
(%i1) A:matrix([2*(a^2+b^2+c^2)])
(%o1) [ 2 2 2 ]
[ 2 (c + b + a ) ]
(%i2) a^2+b^2+c^2 = 1
2 2 2
(%o2) c + b + a = 1
(%i3) solve(%,a^2)
2 2 2
(%o3) [a = (- c ) - b + 1]
(%i4) tellrat(%[1])
2 2 2
(%o4) [c + b + a - 1]
(%i5) algebraic:true
(%o5) true
(%i6) rat(A)
(%o6)/R/ [ 2 ]
(%i7) untellrat(a)
(%o7) []

Maxima: How to factor a expression in an expected form

I have an expression:
(b+2*ab+a+1)/c
I want to use Maxima to factor the equation treating (b+1) as a factor.
i.e. I want the expression in the following form:
[(b+1)(1+a)+ab]/c
Any help would be appreciated.
Well, my advice is first isolate the numerator, then get the quotient and remainder after dividing by b + 1, then put the pieces back together.
(%i1) display2d : false $
(%i2) expr : (b + 2*a*b + a + 1)/c $
(%i3) num (expr);
(%o3) 2*a*b+b+a+1
(%i4) divide (num (expr), b + 1);
(%o4) [2*a+1,-a]
(%i5) first(%o4) * (b + 1) + second(%o4);
(%o5) (2*a+1)*(b+1)-a
(%i6) (first(%o4) * (b + 1) + second(%o4)) / denom (expr);
(%o6) ((2*a+1)*(b+1)-a)/c
(%i7) is (equal (%o6, expr));
(%o7) true
Note that divide returns two values; first is the quotient and second is the remainder.

Resources