Consider the following statements:
(%i1) matchdeclare([a,b], constantp);
(%o1) done
(%i2) defmatch(match, a*x+b);
(%o2) match
(%i3) match(2*x+3);
(%o3) [b = 3, a = 2]
I want to generalise this pattern in a function. But then it doesn't seem to work anymore:
(%i1) matchForm(test, form, constants) := block(
matchdeclare(constants, constantp),
defmatch(match, form),
match(test)
);
(%o1) matchForm(test, form, constants) :=
block(matchdeclare(constants, constantp), defmatch(match, form), match(test))
(%i2) test: 2*x+3;
(%o2) 2 x + 3
(%i3) form: a*x+b;
(%o3) a x + b
(%i4) constants: [a,b];
(%o4) [a, b]
(%i5) matchForm(test, form, constants);
defmatch: evaluation of atomic pattern yields: a x + b
(%o5) false
Debugging a bit, a bit it seems like the issue is that matchdeclare doesn't accept the argument to be a variable. Is ther any way to make a function like I try to make in maxima?
I haven't tried this, but: perhaps you can get the effect you want via
apply (matchdeclare, [constants, 'constantp]),
which will evaluate constants before calling matchdeclare.
Related
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 want to understand how dependencies in Maxima for differentiation work
for iterated cases.
I tried here:
(%i1) depends([f],[x,y]);
(%o1) [f(x,y)]
(%i2) depends([g],[x,y]);
(%o2) [g(x,y)]
(%i3) depends([x,y],[ε]);
(%o3) [x(ε),y(ε)]
(%i4) diff(g,ε);
(%o4) (g[y])*(y[ε])+(g[x])*(x[ε])
(%i5) h(x,y):=f(x,y)+g(x,y);
(%o5) h(x,y):=f(x,y)+g(x,y)
(%i6) diff(h(x,y),ε);
(%o6) g(x,y)[ε]+f(x,y)[ε]
(%i7) diff(h,ε);
(%o7) 0
In (%o4) I get the total derivative with respect to \epsilon. Whereas in (%o6) the derivatives of x and y with respect to \epsilon are not shown. Why?
And can I make Maxima to show these derivatives in the result?
Dependencies declared by depends are only recognized for symbolic, undefined functions. The dependency is associated with the function name (a symbol).
A function with an actual definition, as defined by := or define, is not recognized. The body of the function could contain any combination of other functions, so the only way to know on which other functions the function depends is to evaluate the function body. That is what is happening when you write diff(h(x, y), ε).
Initializing a defstruct using new or without new, seems to do the same, is there any difference?
(%i1) defstruct(foo(a,b));
(%o1) [foo(a, b)]
(%i2) f: foo(1,2);
(%o2) foo(a = 1, b = 2)
(%i3) f#a;
(%o3) 1
(%i4) f_new: new(foo(1,2));
(%o4) foo(a = 1, b = 2)
(%i5) f_new#a;
(%o5) 1
(%i6)
Without using new, the code seems a bit shorter and easier, but I'm not sure if some code will break if I use this pattern.
I think both ways are OK. The only difference so far as I know is that new(foo(...)) will ensure that there are the correct number of initial values. For example new(foo(1)) and new(foo(1, 2, 3)) will give errors, with foo as defined above. Just writing foo(1) or foo(1, 2, 3) doesn't trigger an error (maybe it should).
In maxima, is the following behavior intended?
First example:
(%i1) declare(a,constant);
(%o1) done
(%i2) constantp(a);
(%o2) true
(%i3) square(a):=a^2;
define: in definition of square, found bad argument a
-- an error. To debug this try: debugmode(true);
(%i4) load("linearalgebra.mac");
define: in definition of dotproduct, found bad argument a
-- an error. To debug this try: debugmode(true);
Second example:
(%i1) a:5;
(%o1) 5
(%i2) constantp(a);
(%o2) true
(%i3) square(a):=a^2;
2
(%o3) square(a) := a
(%i4) square(a);
(%o4) 25
Third example:
(%i1) declare(a,scalar);
(%o1) done
(%i2) mat_f(a,b):=a.b - b.a;
(%o2) mat_f(a, b) := a . b - b . a
(%i4) mat_f(matrix([1,2],[3,4]),matrix([3,4],[1,2]));
[ - 10 - 14 ]
(%o4) [ ]
[ 6 10 ]
It seems like declare(a,constant) has a global effect which to me seems strange in maxima. The second and third example work exactly how I would expect it.
Also are there any similar cases where something like this happens in maxima?
Maxima has a very weak notion of scope. Essentially all symbols are in the same scope, so when you make a declaration about a, it is about all instances of a, even the ones which are function arguments.
Maxima is actually a very old program and this is one of those aspects which has never been updated. There is discussion about giving Maxima a stronger notion of scope, but that will take some time.
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.