maxima returns wrong result when using subscripts - maxima

I am using WxMaxima for some calculations so I can export the results directly into my LaTeX file. I have some Greek variables with Greek subscripts which are giving me a headache. In the past in Maxima I used to put the subscripts in the bracket []. But I have noticed that the conventional LaTeX syntax of _ also works. Except it doesn't work for greek letters:
So I have to use the brackets one [] when I want to subscript the Greek letters with Greek letters. But it is causing some calculation errors.
For example consider two simple functions:
%epsilon[r](r):=c[1]-c[2]/r^2;
%epsilon[%theta](r):=c[1]+c[2]/r^2;
now if I run:
fullratsimp(%epsilon[r](r)+%nu*%epsilon[%theta](r));
it gives me:
((c[1]*%nu+c[1])*r^2+c[2]*%nu+c[2])/r^2
Which is obviously wrong because the correct result can be calculated by:
fullratsimp((c[1]-c[2]/r^2)+%nu*(c[1]+c[2]/r^2));
I would appreciate if you could help me know what is the problem and how I can solve it.

The problem is that foo[x1](y) := ... and foo[x2](y) := ... defines just one function foo, and the second definition clobbers the first one, so that only foo[x2](y) := ... is defined.
You can get the effect you want by creating lambda expressions (unnamed functions) and assigning them to subscripted variables.
(%i1) %epsilon[r](r):=c[1]-c[2]/r^2 $
(%i2) %epsilon[%theta](r):=c[1]+c[2]/r^2 $
(%i3) %epsilon[r];
c
2
(%o3) lambda([r], -- + c )
2 1
r
(%i4) %epsilon[%theta];
c
2
(%o4) lambda([r], -- + c )
2 1
r
(%i5) kill(%epsilon) $
(%i6) %epsilon[r] : lambda([r], c[1]-c[2]/r^2) $
(%i7) %epsilon[%theta] : lambda([r], c[1]+c[2]/r^2) $
(%i8) %epsilon[r];
c
2
(%o8) lambda([r], c - --)
1 2
r
(%i9) %epsilon[%theta];
c
2
(%o9) lambda([r], c + --)
1 2
r
(%i10) fullratsimp(%epsilon[r](r)+%nu*%epsilon[%theta](r));
2
(c %nu + c ) r + c %nu - c
1 1 2 2
(%o10) ------------------------------
2
r
Note that foo[x](y) := ... also creates lambda expressions, but you need to ensure your own definition here, not the definition which is created automatically by Maxima.

Related

Simplification of rational expressions

I'm struggling with getting maxima to simplify expressions in the way that I want them.
rhs(solve(a*x-3=b*y,x)[1]);
returns
(b*y+3)/3
However, I'm wanting to display the result to students and so I want the output to be
(b*y/3) + 1
Is there some simplification that I can do to a rational expression in this form to get the output I want?
You can undo the effect of ratsimp in this case by dividing each term in the numerator by the denominator. Here is a simple-minded implementation:
(%i1) unratsimp (e) :=
block ([foo, bar],
[foo, bar]: [num(e), denom(e)],
map (lambda ([foo1], foo1/bar), expand (foo))) $
(%i2) 1 + a/b + c*d/3 - %pi*x/y;
%pi x c d a
(%o2) (- -----) + --- + - + 1
y 3 b
(%i3) ratsimp(%);
(b c d + 3 b + 3 a) y - 3 %pi b x
(%o3) ---------------------------------
3 b y
(%i4) unratsimp(%);
%pi x c d a
(%o4) (- -----) + --- + - + 1
y 3 b
(%i5) unratsimp((b*y + 3)/3);
b y
(%o5) --- + 1
3
I don't know how general that is; it's just the first thing I tried, but maybe it's enough for your purpose. I don't know a built-in function for this.
The results %o4 and %o5 are maybe not exactly as a human would write them. Convincing Maxima to display the terms in + and * expressions in a different way is not straightforward -- Maxima has strong ideas about how to order terms in an expression which are assumed throughout the code. But I think that others have asked questions, which might have answers, about displaying expressions -- you might search Stackoverflow if you are are interested.
The command you can use here is multthru:
(%i1) e1:(b*y+3)/3;
(%o1) (b*y+3)/3
(%i2) multthru(e1);
(%o2) (b*y)/3+1
In this case also the following will work
(%i3) distrib(e1);
(%o3) (b*y)/3+1
(%i4) expand(e1);
(%o4) (b*y)/3+1

How to output equation without evaluation, but with variables replaced to their values?

I need to make tons of simple computations and present each step in my report with predefined manner:
(for ex i got B=2, C=3):
A=B+12-6/C^2; A=2+12-6/3^2=13.333;
I can get 1st block and answer like this:
B:2$ C:3$
A:'(B+12-6/C^2)$
print("A=",A,"; ","A= ??? =",ev(A, numer) );
and get:
6
A= (- --) + B + 12 ; A= ??? = 13.33333333333333
2
C
What i need instead of '???' to get desired output?
Maxima distinguishes two parts of figuring out a result: evaluation and simplification. Evaluation = substituting one thing (the value) for another thing (a variable or a function). Simplification = applying mathematical identities to get a "simpler", equivalent result.
In your problem, it appears you want to postpone simplification. You can say simp: false to do that. Here's one possible approach. I'll disable simplification, substitute values into the expression, print the substituted expression, and then re-enable simplification to get the final result.
(%i2) expr: A=B+12-6/C^2;
6
(%o2) A = (- --) + B + 12
2
C
(%i3) simp: false $
(%i4) subst ([B = 2, C = 3], expr);
- 2
(%o4) A = 12 + 2 + (- 6) 3
(%i5) simp: true $
(%i6) %o4;
40
(%o6) A = --
3
Note that many operations in Maxima happen by simplification (e.g. adding numbers together), so in general, Maxima will act noticeably different when simp is false. But in this case that's what you want.
EDIT: OP points out that the result after substitution is displayed in a somewhat different from. The reason for this has to do with some obscure implementation details of Maxima. Be that as it may, it's possible to work around that behavior by using the Lisp substitution function SUBST (referenced in Maxima as ?subst) instead of Maxima subst. SUBST is a little different than Maxima subst; the syntax is ?subst(new_thing, old_thing, some_expression). After substituting via SUBST, it's necessary to resimplify explicitly; one way to do that is to say expand(..., 0, 0) (which doesn't expand anything, the only effect is to resimplify).
(%i2) expr: A=B+12-6/C^2;
6
(%o2) A = (- --) + B + 12
2
C
(%i3) simp: false $
(%i4) ?subst (3, C, ?subst (2, B, expr));
6
(%o4) A = (- --) + 2 + 12
2
3
(%i5) simp: true $
(%i6) expand (%o4, 0, 0);
40
(%o6) A = --
3
Since SUBST is has a different effect on the internal representation, it is possible you could create an invalid expression, for some choices of new_thing, old_thing, and some_expression. I won't try to sort that out here.

Integrating a piecewise defined function in maxima

Say that I have the following function:
f(x) := if x<=0 then 0 else if x<=1 then 1 else -1;
Or any other piecewise defined function.
The function definition seems to work:
(%i9) f(-11);
f(1/2);
f(2);
(%o7) 0
(%o8) 1
(%o9) -1
However integration doesn't evaluate here. It is somehow possible to get the value of the integral here in Maxima? And if not, could it be done numerically in maxima?
load(abs_integrate) to get the abs_integrate package, which enables integrate to handle unit_step. You'll have to write your piecewise function in terms of unit_step. E.g.:
(%i1) load (abs_integrate) $
(%i2) e : unit_step(t) - 2*unit_step(t - 1) $
(%i3) integrate (e, t, a, b);
abs(b) - b - 2 abs(b - 1) - abs(a) + a + 2 abs(a - 1)
(%o3) -----------------------------------------------------
2
For numerical integration, quad_qags (and other quadpack functions) can handle both unit_step and if expressions. quad_qags doesn't need abs_integrate.

How to pass an array as an argument to a maxima function?

I'm working on creating maxima functions to simplify the del operator on vectors. How can I pass a list/vector to a function in maxima? This works:
(%i7) dot(a,b) := a[1]*b[1]+a[2]*b[2]+a[3]*b[3];
(%o7) dot(a, b) := a b + a b + a b
1 1 2 2 3 3
(%i8) dot(a,b);
2
(%o8) 3 x y - 4 x
but this doesn't:
(%i13) grad(a) := diff(a[1],x) + diff(a[2],y) + diff(a[3],z);
define: argument cannot be an atom or a subscripted memoizing function; found:
a
-- an error. To debug this try: debugmode(true);
Maxima has extremely confusing rules about scope and subscripts. First of all, I'll apologize for that.
My guess is that you already have an array named a by the time you define grad. Try a different name for the argument of grad -- try something which you haven't used yet. Does it work that way?
Anyway, shouldn't the definition be:
grad(a) := [diff(a, x), diff(a, y), diff(a, z)];
??

Maxima - Effect of the commas when not in a function

With Maxima, it is possible to replace an unknown by a value using at() statement.
But this use a list, for the substitution, and the solve() statement don't return a list.
Code:
(%i1) g(x):=x^2+a;
2
(%o1) g(x) := x + a
(%i2) g(x),solve(x=3),a=2;
(%o2) 11
I managed to compute a result using commas, but I can't create a function to do so:
(%i3) f(y) := g(x),solve(x=3),a=y;
(%o3) f(y) := g(x)
(%i4) f(2);
2
(%o4) x + a
Is there a statement for which the commas acts like it acts directly in the line?
Edit:
Actually, it is possible to use at() with solve() to create the function f(), as solve() just return a list of lists. So the code would be:
(%i5) f(y) := at(at(g(x), solve(x=3)[1]), a=y);
(%o5) f(y) := at(at(g(x), solve(x = 3) ), a = y)
(%i6) f(2);
(%o6) 11
Notice the [1] after solve(x=3) in the (%i5). It select the the first item (solution) of list.
I'm not sure what you are trying to accomplish -- probably it would be best if you would back up a couple of steps and describe the larger problem you are trying to solve here.
My best guess as to what you want is that you are trying to use the result of 'solve' to find a value to substitute into some expression. If so you can achieve it like this: f(eq, u) := map (lambda ([e], subst (e, g(u))), solve (eq, x)); where eq is an equation to solve for x and then substitute into g(u). Note that 'solve' can return multiple solutions so that's why I use 'map' to apply something to each solution. Here is an example output:
(%i7) f(eq) := map (lambda ([e], subst (e, g(x))), solve (eq, x));
(%o7) f(eq) := map(lambda([e], subst(e, g(x))), solve(eq, x))
(%i8) solve (x^2 + 2*x + 2);
(%o8) [x = - %i - 1, x = %i - 1]
(%i9) f (x^2 + 2*x + 2);
(%o9) [g(- %i - 1), g(%i - 1)]
Of course you can define 'g' in whatever way is appropriate.
The answer to your specific question (which I believe is not actually very much relevant, but anyway) is to use 'block' to group together expressions to be evaluated. E.g. f(x) := block (...);
Perhaps I'm answering the wrong question. Maybe what you want is ev(foo, bar, baz) -- ev is the function that is actually called when you write foo, bar, baz at the console input prompt. So the function would be written f(y) := ev (g(x), solve(x=3), a=y).
However, bear in mind that there are several different kinds of functionality built into ev, so it is hard to understand (see the documentation for ev). Instead, consider using subst which is much simpler.

Resources