As an example I want to try to find the partial derivatives of
f(x) = \sum_{i=1}^n x_i^2
in Maxima. (The expected output would be \frac{\partial f}{\partial x_k} = 2x_k) I have tried following, but it seems the indexed variables are not handled as I expected, can anyone explain what I am doing wrong?
The same command works if you replace n and k with actual numbers, but not in this form:
f(x) := 1/2 * sum( x[i]^2, i, 1, n);
print(diff(f(x),x[k]));
Try it online!
Maxima can't handle derivative with respect to a indexed variable by default. I wrote a couple of small packages to handle these problems. Perhaps this is useful to you.
See: https://pastebin.com/MmYJRqCq (sum_kron_delta, summation of Kronecker delta)
and: https://pastebin.com/UGCPgvAn (diff_sum, derivative of summation wrt indexed variable)
Here's an example applied to your problem. I'll assume you have downloaded the code above to your computer.
(%i1) load ("sum_kron_delta.mac");
(%o1) sum_kron_delta.mac
(%i2) load ("diff_sum.mac");
(%o2) diff_sum.mac
(%i3) 'diff ('sum (x[i]^2, i, 1, n), x[j]);
n
====
\
(%o3) 2 > x kron_delta(i, j)
/ i
====
i = 1
Note that you have to write 'diff('sum(... that is, with the quote mark ' to indicate that diff and sum are nouns (formal expressions) instead of verbs (functions which are called). This is necessary in the implementation of diff_sum and sum_kron_delta because they work with simplification rules. (It's a long story, which I can explain if there's interest.)
I see we got the kron_delta summation, but we need to cause the simplification rules to be applied. We could also write expand(%, 0, 0) here instead of ''%.
(%i4) ''%;
(%o4) 2 (if (1 <= j) and (j <= n) and %elementp(j, integers) then x else 0)
j
At this point we have the final result, which we can simplify further with additional data.
(%i5) assume (j >= 1, j <= n);
(%o5) [j >= 1, n >= j]
(%i6) ''%o4;
(%o6) 2 (if %elementp(j, integers) then x else 0)
j
(%i7) declare (j, integer);
(%o7) done
(%i8) ''%o6;
(%o8) 2 x
j
If this seems fruitful to you, I'll be happy to go into details.
Related
I have series of simple equations, which has one input variable x and handful of helper variables, and the result should be an expression in terms of x. Those equations have if/then/else in them. How can I force the final result to only have if/then/else at top level, and not in subexpressions? Ideally I want to receive a result that resembles jagged linear plot equation in the form of if x < step1 then m1 * x + k1 else if x < step2 then m2 * x + k2 else ... where step, m and k would be numeric constants. To give an example, I have
eq1: var1 = if x > 1678 then 400 - 0.18*(x - 642) else 460 - 0.26*(x-730);
eq2: var2 = subst([eq1], if x <= 7520.5 then (x - var1)*0.2 else 7520.5*0.2+(x - 7520.5)*-0.32);
eq3: x - var2;
res: subst([eq1, eq2], eq3);
expand(res);
which currently evaluates to
x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x)
Great question, unfortunately, I don't see an easy way to do that. Here is a sketch of some ideas; I'll try to come back in the next day or two to fill in the details.
First of all, I thought about replacing if/then/else with unit_step, charfun, or charfun2. However, it looks like simplifications for arithmetic on those expressions (e.g. product of unit_step) isn't implemented, so working with any of those wouldn't be any simpler. But if someone else can see how to do it, please, by all means, show us.
The outline of a way that I see to do this is (1) define rules for arithmetic on if/then/else, and (2) define rules for flattening nested if/then/else. I would use defrule to define the rules, although tellsimpafter is also a possibility.
EDIT: I've put together some code to handle (1) and (2) above. See robert-dodier/simplify_conditionals at: https://github.com/maxima-project-on-github/maxima-packages
Here's the result I get for the problem you mentioned.
(%i2) load ("simplify_conditionals.mac");
(%o2) simplify_conditionals.mac
First assign e the expression you showed.
(%i3) e: x-(if x<=7520.5 then 0.2*x-0.2*(if x>1678 then 515.56-0.18*x else 649.8-0.26*x) else 3910.66-0.32*x);
(%o3) x - (if x <= 7520.5 then 0.2 x
- 0.2 (if x > 1678 then 515.56 - 0.18 x else 649.8 - 0.26 x)
else 3910.66 - 0.32 x)
Carry out + and * arithmetic. (- and / are also covered since those are defined in terms of + and * in Maxima.)
(%i4) arithmetic_with_conditionals (e);
(%o4) if x <= 7520.5 then (if x > 1678
then 0.8 x + 0.2 (515.56 - 0.18 x)
else 0.8 x + 0.2 (649.8 - 0.26 x)) else 1.32 x - 3910.66
Call expand to distribute * over + (this is aside from the conditional stuff).
(%i5) e1: expand (%);
(%o5) if x <= 7520.5 then (if x > 1678 then 0.764 x + 103.112
else 0.748 x + 129.96) else 1.32 x - 3910.66
Flatten nested conditionals.
(%i6) e2: flatten_conditionals (e1);
(%o6) if (x <= 7520.5) and (x > 1678) then 0.764 x + 103.112
elseif x <= 7520.5 then 0.748 x + 129.96 else 1.32 x - 3910.66
Okay, that's it. At this point you could verify the result by, e.g., plotting both e and e2 and verifying they're the same, or evaluating e2 - e for values of x and verifying the result is zero or nearly so (since floating point arithmetic can yield very small, nonzero results).
I made some effort to verify the implementation; see rtest_simplify_conditionals.mac. But the tests aren't exhaustive. Also, I didn't try to handle other operations, e.g. exponents or arbitrary functions. All the same, I hope the package is useful to you in some way.
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
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.
I want to check if some maxima input is of a specific form. For example, I want to check if the answer is of the form A*%e^(B*t) where A and B are specific real numbers.
If student X gives answer 3*%e^(5*t), then it is of this form. If student Y gives answer sin(t), or maybe y=3*%e^(5*t) then I can give this student as feedback that his answer is not yet of the correct form.
I was wondering if there exist something like this in maxima.
Maxima has several pattern-matching functions that operate on expressions (not strings). I think defmatch is suitable here, e.g.:
(%i8) matchdeclare ([A, B], constantp);
(%o8) done
(%i9) defmatch (match_aexpbt, A*exp(B*t), t);
(%o9) match_aexpbt
(%i10) match_aexpbt (5*exp(3*u), u);
(%o10) [A = 5, B = 3, t = u]
(%i11) match_aexpbt (sqrt(2)*exp(%pi*z), z);
(%o11) [A = sqrt(2), B = %pi, t = z]
(%i12) match_aexpbt (y = 5*exp(3*u), u);
(%o12) false
(%i13) match_aexpbt (5*sin(2*u), u);
(%o13) false
(%i14) match_aexpbt ((1 + %i)*exp(exp(%pi)*v), v);
%pi
(%o14) [A = %i + 1, B = %e , t = v]
In this case I've defined match_aexpbt which matches expressions which look like A*exp(B*t) where A and B are constants and t is a variable which is supplied.
See the documentation for defmatch and matchdeclare and also defrule, tellsimp, and tellsimpafter. The pattern-matching functions are a little idiosyncratic but actually pretty useful -- I have used them many times.
If you are interested in checking student's answers, there have been projects based on Maxima for that. Take a look at the related projects webpage and see in particular STACK.
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.