How to expand in taylor series a composition of functions? - maxima

I would like to expand in taylor series a function of type : f(x+f(x)) around x=a in the case where f(a)=0.
(%i1) atvalue(f(x),[x=a],0)$
The direct calculus yields :
(%i2) taylor(f(x+f(x)),x,a,2);
(%o2)/T/ f(a)+(at('diff(f(f(x)+x),x,1),x=a))*(x-a)+((at('diff(f(f(x)+x),x,2),x=a))*(x-a)^2)/2+...
If I define a intermediate function :
(%i3)define(tf(x),taylor(f(x),x,a,2))$
Then a expand in Taylor series I get :
(%i4) taylor(f(x+tf(x)),x,a,2);
(%o4) 0+...
I expect the following result :
f(1+f'(a))f'(a)(x-a)+(x-a)^2 f''(a)[f'(a)+(1+f'(a))^2/2]+o(x-a)^2
How could I solve this problem?

You can use gradef to simplify notation.
gradef(f(x), f1(x)) $
gradef(f1(x), f2(x)) $
atvalue(f(x), x = a, 0) $
e: f(x+f(x)) $
e: taylor(e, x, a, 2) $
e: expand(e, 0, 0)$ /* 'taylor' form to ordinar expression */
e: ev(e, nouns); /* f(a) to 0 */
returns
2 2
(f1 (a) f2(a) + 3 f1(a) f2(a) + f2(a)) (x - a)
(%o7) -----------------------------------------------
2
2
+ (f1 (a) + f1(a)) (x - a)

A solution is as follow :
gradef(f(x), f1(x)) $
gradef(f1(x), f2(x)) $
atvalue(f(x), x = a, 0) $
e: f(x+f(x)) $
e: taylor(e, x, a, 2) $
e: expand(e, 0, 0)$ /* 'taylor' form to ordinar expression*/
e: ev(e, nouns); /* f(a) to 0 */
taylor(e,x,a,2); /* Becomes again a taylor serie which could be reused*/
For example, if I want to find the order of the Steffensen method which is defined, for function f which is C^2 and f(a)=0,f'(a)!=0, by :
Sf(x)=x-f(x)^2/(f(x+f(x)-f(x))
If I straight expand this function around a I get :
Sf(x)=a+(x-a)-(f1(a)^2*(x-a)^2)/f(a)+...
which diverges since f(a)=0.
So this must be proceed in two steps. First I expand the denominator :
den:f(x+f(x))-f(x)$
t:taylor(den,x,a,2);
t: expand(t, 0, 0)$
t: ev(t, nouns)$
t:taylor(t,x,a,2);
Then I expand the function Sf:
Sf:x-f(x)^2/(t)$/*Introducing the taylor serie of den*/
taylor(Sf,x,a,2);
which provides the wanted result :
Sf(x)=a+((f1(a)+1)*f2(a)*(x-a)^2)/(2*f1(a))+...

Related

Equation not fully solved for

I've been trying to solve an equation for a 2D vector P.
But after solve there are still some P on the rhs.
Does this mean Maxima can't do it or I've done something wrong?
Here is it:
load("vect");
declare(".", commutative);
declare(P, nonscalar);
declare([v1,V1,r1], nonscalar);
declare([v2,V2,r2], nonscalar);
declare([w1,W1,m1,I1,w2,W2,m2,I2], scalar);
/* Revolute Constraint */
constraint: v2 + (w2~r2) - (v1 + (w1~r1)) = 0$
/* Velocities after impulse P */
eq1: v1 = V1 - P/m1$
eq2: w1 = W1 - (r1~P) / I1$
eq3: v2 = V2 + P/m2$
eq4: w2 = W2 + (r2~P) / I2$
eq: subst([eq1,eq2,eq3,eq4], constraint)$
solve(eq, P);
(I'm trying to get an equation for an impulse that satisfies the constraint.
I'm following Dirk Gregorius' 2nd post here: https://gamedev.net/forums/topic/469531-revolute-joint-usingimpulses/4086845)
I think I've worked out the details. I had to do some stuff by hand, and Maxima was mostly just checking that I did it correctly. If the goal is just to get to a solution, I guess that's okay.
Here's my script. You can execute this via: maxima --batch=foo.mac where foo.mac is the name of the script.
/* adapted from: https://stackoverflow.com/questions/69700162/equation-not-fully-solved
*/
load("vect");
/* I don't want to reorder arguments of cross product. */
remrule ("~", ?\~rule4);
/* I do want to flatten noncommutative multiplication.
* (It appears that's disabled by vect; ordinarily it happens by default.)
*/
dotassoc: true $
declare(P, nonscalar);
declare([v1,w1,V1,W1,r1], nonscalar);
declare([v2,w2,V2,W2,r2], nonscalar);
declare([m1,I1,m2,I2], scalar);
/* Revolute Constraint */
constraint: v2 - (r2~w2) - (v1 - (r1~w1)) = 0$
/* Velocities after impulse P */
eq1: v1 = V1 - P/m1$
eq2: w1 = W1 - (r1~P) / I1$
eq3: v2 = V2 + P/m2$
eq4: w2 = W2 + (r2~P) / I2$
eq: subst([eq1,eq2,eq3,eq4], constraint);
A(a) := matrix([0, -a[3], a[2]], [a[3], 0, -a[1]], [-a[2], a[1], 0]);
eqa: ev (eq, (u~v) := 'A(u).v);
matchdeclare (pp, lambda ([e], not freeof(P, e)));
matchdeclare (qq, lambda ([e], freeof(P, e)));
defrule (rp, pp + qq = 0, pp = -qq);
eqa1: expand (eqa);
eqa2: apply1 (eqa1, rp);
matchdeclare (aa, lambda ([e], matrixp(e) or listp(e)));
tellsimpafter (I(aa), ident (length (aa)));
matchdeclare ([aa, bb], all);
tellsimpafter (I(aa) . bb, bb);
tellsimpafter (aa . I(bb), aa);
M: -(1/I2)*'A(r2).'A(r2) - (1/I1)*'A(r1).'A(r1) + (1/m2)*I(P) + (1/m1)*I(P);
N: 'A(r2).W2 - 'A(r1).W1 - V2 + V1;
eqa2_factored: M . P = N;
expand (eqa2_factored);
?resimplify (%);
if % # eqa2 then error ("tried to factor eqa2, but something went wrong.");
solution: P = M^^-1 . N;
/* EXAMPLE: */
I1: 20 $
I2: 3 $
m1: 100 $
m2: 12 $
V1: [17, 19, -23] $
V2: [-5, -3, 11] $
W1: [8, 4, 14] $
W2: [-6, -16, 24 ] $
r1: [1/2, 2/3, 3/4] $
r2: [5, 7, 3] $
/* note various subterfuges to ensure evaluation with stated values */
example_M: ev (subst (I(P) = ident(3), M), nouns);
example_N: ev (N, nouns);
example_P: example_M^^-1 . example_N;
subst (P = example_P, ev (eqa2, eval, nouns));
if lhs(%) = rhs(%)
then print ("TEST PASSED: lhs = rhs")
else error ("TEST FAILED: lhs # rhs");
If you need to evaluate P for different parameters r1, r2, etc., my advice is to evaluate matrix M and vector N with whatever values you want to plug in, and then solve the equation P = M^^-1 . N. An explicit solution is probably going to be pretty messy.
Following Robert Dodier's advice, I broke up all the vectors and solved for P[1] and P[2] individually.
I've got something that gives me an answer but now how can I get it into nice vector form?
Here it is:
load("vect");
declare(".", commutative);
declare(P, nonscalar);
declare([v1,V1,r1], nonscalar);
declare([v2,V2,r2], nonscalar);
declare([w1,W1,m1,I1], scalar);
declare([w2,W2,m2,I2], scalar);
cross_scalar_vector(s,v) := [-s*v[2], s*v[1]]$
/* Revolute Constraint on Linear Velocity */
constraint: v2 + cross_scalar_vector(w2,r2) - (v1 + cross_scalar_vector(w1,r1)) = [0,0]$
/* Sub in velocities after impulse P. */
post_velocities: [
v1 = V1 - P/m1,
w1 = W1 - (r1~P) / I1,
v2 = V2 + P/m2,
w2 = W2 + (r2~P) / I2
]$
constraint: subst(post_velocities, constraint)$
/* Break up the remaining vectors for solve. */
vectors: [
P = [P[1], P[2]],
V1 = [V1[1], V1[2]],
r1 = [r1[1], r1[2]],
V2 = [V2[1], V2[2]],
r2 = [r2[1], r2[2]]
]$
constraint: subst(vectors, constraint)$
/* Break up vector constraint into x and y constraint for solve. */
xconstraint: lhs(constraint)[1] = 0$
yconstraint: lhs(constraint)[2] = 0$
/* Not sure why we need to do this again? */
xconstraint: subst(vectors, xconstraint)$
yconstraint: subst(vectors, yconstraint)$
/* Expand cross products for solve. */
xconstraint: express(xconstraint)$
yconstraint: express(yconstraint)$
solve([xconstraint,yconstraint], [P[1],P[2]]);

Transforming Equations WxMaxima Ezunits

I'm having problems transforming equations, again...
Setting up the functions b(a) and c(b) works. Inserting them into each other also works to get from a temperature to a current c(b(a)). But now I want to flip it around a(c). The result should be like this a(c):= (c-(4`mA))*(25`degC)/(4`mA); But it's not working even with the ''-trick.
(%i1) load(ezunits);
(%o1) "C:/maxima-5.44.0/share/maxima/5.44.0/share/ezunits/ezunits.mac"
(%i7) a0: 0`degC;
am: 100`degC;
b0: 0`mV;
bm: 4`mV;
c0: 4`mA;
cm: 20`mA;
(a0) 0 ` degC
(am) 100 ` degC
(b0) 0 ` mV
(bm) 4 ` mV
(c0) 4 ` mA
(cm) 20 ` mA
(%i8) b(a):= (bm-b0)/(am-a0)*(a-a0)+b0;
(%o8) b(a):=(bm-b0)/(am-a0)*(a-a0)+b0
(%i9) c(b):= (cm-c0)/(bm-b0)*(b-b0)+c0;
(%o9) c(b):=(cm-c0)/(bm-b0)*(b-b0)+c0
(%i10) c(b(50`degC));
(%o10) 12 ` mA
(%i11) a(c):= dimensionally(solve(c(b(T)), T));
(%o11) a(c):=dimensionally(solve(c(b(T)),T))
(%i12) a(12`mA);
(%o12) [T=(-25) ` degC]
(%i13) a(c):= ''(dimensionally(solve(c(b(T)), T)));
(%o13) a(c):=[T=(-25) ` degC]
(%i14) a(12`mA);
(%o14) [T=(-25) ` degC]
(%i15) oi: T, dimensionally(solve(c(b(T)), T));;
(oi) (-25) ` degC
(%i16) a(c):= (c-(4`mA))*(25`degC)/(4`mA);
(%o16) a(c):=((c-4 ` mA)*(25 ` degC))/4 ` mA
(%i17) a(12`mA);
(%o17) 50 ` degC
-->
It looks like you have omitted the specific value of c from solve(c(b(T)), T) -- what I mean is you need something like solve(c(b(T)) = c1, T) where c1 is the input value such as 12 ` mA.
This definition seems to work --
a(c1):= dimensionally(solve(c(b(T)) = c1, T));
Then I get
(%i22) a(12`mA);
(%o22) [T = 50 ` degC]
When you omit the ... = c1, you are effectively solving for ... = 0, that's why you get T = (- 25) ` degC.
The other variation a(c1) := ''(...) should also work, although I didn't try it.
You can write a(c) := dimensionally(solve(c(b(T)) = c, T)), i.e., using the same name for the variable c and the function c, but it's easy to get mixed up, and also I am hoping the change that behavior in the near future (with the implementation of lexical scope of symbols) which will make that not work anymore.

Rearrange equation using Maxima

In Maxima I have an equation that is like:
eq : c0*a + d0*a + c1*b - c2*p - c4*q = c5*r
Is there a command that allows me to arrive at:
(c0 + d0)*a + c1*b = c2*p + c4*q + c5*r
In short, I want to choose which variables end on either the left or right hand side and I want to write it such that there is only one occurence of the variables I select (in this case a, b, p, q, r).
Perhaps coefmatrix is useful for this.
(%i1) display2d : false $
(%i2) eq : c0*a + d0*a + c1*b - c2*p - c4*q = c5*r $
(%i3) vars : [a, b, p, q, r] $
(%i4) coeffs : coefmatrix ([eq], vars);
(%o4) matrix([d0+c0,c1,-c2,-c4,-c5])
(%i5) coeffs . vars;
(%o5) (-c5*r)-c4*q-c2*p+a*(c0+d0)+b*c1
Note that both arguments of coefmatrix must be lists.

How do I use lhs and rhs to define a function?

In the Maxima session below, how come f(1) is not 0?
(%i1) eq: 2 * x + 1 = 3;
(%o1) 2 x + 1 = 3
(%i2) f(x) := lhs(eq) - rhs(eq);
(%o2) f(x) := lhs(eq) - rhs(eq)
(%i3) f(1);
(%o3) 2 x - 2
the process of function calling in maxima here binds x to 1 in the function
definition, lhs(eq)-rhs(eq). That has no x in it, so that binding does nothing.
Next, lhs(eq) is evaluated to 2*x+1. rhs(eq) is evaluated to 3. etc.
Do you always want the same equation eq? perhaps you want to do
define(f(x),lhs(eq)-rhs(eq));
to check what the definition is, try
grind(f);
If you want to vary the equation maybe something like
g(val, eq) := subst(val,x, lhs(eq)-rhs(eq)) ;
would do.

How to print square of n*n given characters in prolog?

Write a Prolog program to print out a square of n*n given characters on the screen. Call your predicate square/2. The first argument should be a (positive) integer. the second argument the character (any Prolog term) to be printed. Example:
?-square(5, '*').
*****
*****
*****
*****
*****
Yes
I just start to learn this language. I did this:
square(_,'_').
square(N, 'B') :-
N>0,
write(N*'B').
It doesn't work at all. Can anyone help me?
So your question is, basically, "how do I write a loop nested in a loop?"
This is how you write an empty loop with an integer for a counter:
loop(0).
loop(N) :- N > 0, N0 is N-1, loop(N0).
which in C would be:
for(i=0; i < n; ++i) { }
And you seem to know already how to print (write(foo)).
Decompose the problem. To write an NxN square, you need to do two things:
Write N lines
Write a single line, consisting of N characters followed by a newline character.
The second is easy:
do_line(0,_) :-
nl
.
do_line(N,C) :-
N > 0 ,
write(C) ,
N1 is N-1 ,
do_line(N1,C)
.
The first isn't much more difficult:
do_lines(0,_,_).
do_lines(M,N,C) :-
M > 0 ,
do_line(N,C) ,
M1 is M-1 ,
do_lines(M1,N,C)
.
The all you need to do is wrap it:
write_square(N,C) :- do_lines(N,N,C) .
Easy!
You need to draw a line of N stars/characters
line(N,X):- N>0, N1 is N-1, line(N1,X), write(X), fail; true.
Then you will draw a column of N lines of stars/characters.
s(N,Chr):-sAux(N,0,Chr).
sAux(N,N,Chr).
sAux(N,C,Chr):-C<N, C1 is C+1, sAux(N, C1, Chr), line(N,Chr),nl.
s(N,Chr):- N>0, N1 is N-1, s(N1,X), linie(N,X), nl, fail;true.
Doing this:
square2(0,_). % base case, recursion stops when X reaches 0, second argument is irrelevent
square2(X,Symbol):-
X1 is X - 1,
write(Symbol),
square2(X1,Symbol).
With the query, which results in:
?- square2(5,'* ').
* * * * *
Therefore, we need another loop to make it write X times.
square1(0,_,_). % base case, recursion stops when X reaches 0
square1(X,Y,Symbol):-
X1 is X - 1,
square2(Y,Symbol), % with the same Y passed in square2 predicate to print a line of symbols
nl, % creates a new line
square1(X1,Y,Symbol).
However, the question is asking for the format with square(5, '* '). Therefore,
square(X,Symbol):-
square1(X,X,Symbol).
To wrap up:
square(X,Symbol):-
square1(X,X,Symbol).
square1(0,_,_).
square1(X,Y,Symbol):-
X1 is X - 1,
square2(Y,Symbol),
nl,
square1(X1,Y,Symbol).
square2(0,_).
square2(X,Symbol):-
X1 is X - 1,
write(Symbol),
square2(X1,Symbol).

Resources