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

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.

Related

How to substitute expressions containing units when using the ezunits package?

Without specifying units, I can express area and volume and have Maxima show the relationship:
(%i1) areaNoUnits: area = width * length$
(%i2) volumeNoUnits: volume = area * height$
(%i3) volumeNoUnits, areaNoUnits;
(%o3) volume = height length width
(%i4) subst(areaNoUnits, volumeNoUnits);
(%o4) volume = height length width
Now I want to specify units so I will use the ezunits package.
The ` (backtick) operator is the building block of ezunits:
An expression a ` b represents a dimensional quantity, with a indicating a nondimensional quantity and b indicating the dimensional units.
When I add units to the area and volume expressions, evaluation and substitution do not work:
(%i1) load ("ezunits")$
(%i2) areaWithUnits: area ` m^2 = (width ` m) * (length ` m);
2 2
(%o2) area ` m = length width ` m
(%i3) volumeWithUnits: volume ` m^3 = (area ` m^2) * (height ` m);
3 3
(%o3) volume ` m = area height ` m
(%i4) volumeWithUnits, areaWithUnits;
3 3
(%o4) volume ` m = area height ` m
(%i5) subst(areaWithUnits, volumeWithUnits);
3 3
(%o5) volume ` m = area height ` m
The expected output is:
volumeWithUnits, areaWithUnits;
3 3
volume ` m = height length width ` m
I do not see a function in the ezunits package to do evaluation or substitution. What is the right way to do this?
I would phrase it like this:
(%i2) load (ezunits) $
(%i3) width: W ` m;
(%o3) W ` m
(%i4) length: L ` m;
(%o4) L ` m
(%i5) area: width * length;
2
(%o5) L W ` m
(%i6) height: H ` m;
(%o6) H ` m
(%i7) volume: area * height;
3
(%o7) H L W ` m
I wrote each part as conceptualname: symbolforquantity ` unit and then wrote just conceptualname in further calculations, instead of conceptualname ` unit.
The substitution you tried in %i5 didn't work because subst is a purely formal substitution -- if there isn't a literal subexpression which is the same as the substituted-for expression, it doesn't match; subst doesn't look for rearrangements or factorizations which could help make a match. There are ways to work around that, so it might be possible to make your original formulation work, but I think it's better overall to sidestep the problem and work with conceptualname and symbolforquantity ` unit.
To say a little about what more one could do with expressions like %o7 above. There are at least two ways to replace symbols H, L, and W with specific values. One is to call subst:
(%i2) load (ezunits) $
(%i3) volume: H*L*W ` m^3;
3
(%o3) H L W ` m
(%i4) subst ([L = 20, W = %pi], volume);
3
(%o4) 20 %pi H ` m
Another is to make use of ev.
(%i5) ev (volume, L = 20, W = %pi);
3
(%o5) 20 %pi H ` m
Note that at the input prompt, something, someflags, somevalues is equivalent to ev(something, someflags, somevalues).
(%i6) volume, L = 20, W = %pi;
3
(%o6) 20 %pi H ` m
This is just a convenience. Within a function, one has to say ev(...); the shorter syntax isn't understood there.
ev is often convenient, but it's generally simpler to predict what the result is going to be with subst instead.

Maxima: Round like in Excel

Is there a function which rounds numbers (even decimal numbers) like round() in Excel?
Example
Round 1,45 to one decimal: 1,5
Round 2,45 to one decimal: 2,5
There is a similar question but they use a different algorithm.
OK, here's an attempt to reimplement Excel =ROUND function in Maxima. Some notes. (1) Values are rounded to 15 significant digits before applying the user's rounding. This is an attempt to work around problems caused by inexact representation of decimals as floating point numbers. (2) I've implemented excel_round and integer_log10 as so-called simplifying functions. That means that the calculation isn't carried out until the arguments are something that can be evaluated (in this case, when the arguments are numbers). (3) I didn't check to see what Excel =ROUND does with negative numbers -- does it round 5 upward (i.e., towards zero in this case), or away from zero? I dunno.
I've posted this solution as the little package excel_round.mac on Github. See: https://github.com/maxima-project-on-github/maxima-packages and navigate to robert-dodier/excel_round. In the interest of completeness, I've pasted the code here as well.
Here are a few examples.
(%i1) excel_round (1.15, 1);
(%o1) 1.2
(%i2) excel_round (1.25, 1);
(%o2) 1.3
(%i3) excel_round (12.455, 2);
(%o3) 12.46
(%i4) excel_round (x, 2);
(%o4) excel_round(x, 2)
(%i5) ev (%, x = 9.865);
(%o5) 9.87
Here is the code. This is the content of excel_round.mac.
/* excel_round -- round to specified number of decimal places,
* rounding termminal 5 upwards, as in MS Excel, apparently.
* Inspired by: https://stackoverflow.com/q/62533742/871096
*
* copyright 2020 by Robert Dodier
* I release this work under terms of the GNU General Public License.
*/
matchdeclare (xx, numberp);
matchdeclare (nn, integerp);
tellsimpafter (excel_round (xx, nn), excel_round_numerical (xx, nn));
matchdeclare (xx, lambda ([e], block ([v: ev (e, numer)], numberp(v))));
tellsimpafter (excel_round (xx, nn), excel_round_numerical (ev (xx, numer), nn));
excel_round_numerical (x, n) :=
block ([r, r1, r2, l],
/* rationalize returns exact rational equivalent of float */
r: rationalize (x),
/* First round to 15 significant decimal places.
* This is a heuristic to recover what a user "meant"
* to type in, since many decimal numbers are not
* exactly representable as floats.
*/
l: integer_log10 (abs (r)),
r1: round (r*10^(15 - l)),
/* Now begin rounding to n places. */
r2: r1/10^((15 - l) - n),
/* If terminal digit is 5, then r2 is integer + 1/2.
* If that's the case, round upwards and rescale,
* otherwise, terminal digit is something other than 5,
* round to nearest integer and rescale.
*/
if equal (r2 - floor(r2), 1/2)
then ceiling(r2)/10.0^n
else round(r2)/10.0^n);
matchdeclare (xx, lambda ([e], numberp(e) and e > 0));
tellsimpafter (integer_log10 (xx), integer_log10_numerical (xx));
matchdeclare (xx, lambda ([e], block ([v: ev (e, numer)], numberp(v) and v > 0)));
tellsimpafter (integer_log10 (xx), integer_log10_numerical (ev (xx, numer)));
matchdeclare (xx, lambda ([e], not atom(e) and op(e) = "/" and numberp (denom (e)) and pow10p (denom (e))));
pow10p (e) := integerp(e) and e > 1 and (e = 10 or pow10p (e/10));
tellsimpafter (integer_log10 (xx), integer_log10 (num (xx)) - integer_log10_numerical (denom (xx)));
integer_log10_numerical (x) :=
if x >= 10
then (for i from 0 do
if x >= 10 then x:x/10 else return(i))
elseif x < 1
then (for i from 0 do
if x < 1 then x:x*10 else return(-i))
else 0;
The problem of rounding numbers is actually pretty subtle, but here is a simple approach which I think gives workable results. Here I define a new function myround which has the behavior described for Excel =ROUND. [1]
(%i4) myround (x, n) := round(x*10^n)/10.0^n;
n
'round(x 10 )
(%o4) myround(x, n) := -------------
n
10.0
(%i5) myround (2.15, 1);
(%o5) 2.2
(%i6) myround (2.149, 1);
(%o6) 2.1
(%i7) myround (-1.475, 2);
(%o7) - 1.48
(%i8) myround (21.5, -1);
(%o8) 20.0
(%i9) myround (626.3, -3);
(%o9) 1000.0
(%i10) myround (1.98, -1);
(%o10) 0.0
(%i11) myround (-50.55, -2);
(%o11) - 100.0
[1] https://support.microsoft.com/en-us/office/round-function-c018c5d8-40fb-4053-90b1-b3e7f61a213c

How to maintain standard form with binomials such as -x + 1?

I'm using Maxima to print stuff into a web page in an educational context. Most of the time everything works smoothly, but I'm having problems with binomials such as -x + 1, which Maxima simplifies as 1 - x. I quess that this is because this form takes less characters.
But in educational context this is often not desired, as in the standard form the term with x should always be before constant.
So is there any option to prevent this kind of simplification?
I have tried using ratvars(x), totaldisrep(-x+1) and declare(x,mainvar), none of those did what I was looking for.
Outputs:
x + 1;
x+1
x - 1;
x-1
-x - 1;
-x-1
-x + 1;
1-x
I wish to find a way to get this last one to output -x+1.
Try setting negsumdispflag to false. See: ? negsumdispflag
I get these results, maybe this is acceptable.
(%i12) negsumdispflag:false;
(%o12) false
(%i13) x + 1;
(%o13) x + 1
(%i14) x - 1;
(%o14) x - 1
(%i15) 1 - x;
(%o15) (- x) + 1
(%i16) - 1 - x;
(%o16) (- x) - 1

display partial derivatives in maxima

I want to display the partial derivative df/dx of f(x,y) = ln(y-1-x^2)-xy^2.
A comparable example for what I want is:
(%i0) f(x) := x^8$
(%i1) diff(f(x),x);
(%o1) 8*x^7
I've tried:
(%i1) f(x,y):=ln(y-1-x^2)-xy^2$
(%i2) g(x,y):=(diff(f(x,y), x));
(%o2) g(x,y):='diff(f(x,y),x,1)
(%i3) g(x,y):=''(diff(f(x,y), x));
(%o3) g(x,y):='diff(ln(y-x^2-1),x,1)
But it doesn't work (the summand -xy^2 got deleted?).
I want the derivated function. Something like this:
(2*x)
g(x,y):= ——————————— - y^2
(1 + x^2 - y)
the problem with your funciotn is that xy^2 instead of x*y^2for maxima is a variable you should write it as follows:
(%i5) f(x,y):=ln(y-1-x^2)-x*y^2;
(\%o5) f\left(x , \linebreak[0]y\right):=\mathrm{ln}\left(y-1-x^2\right)-x\,y^2
(%i6) diff(f(x,y), x);
(\%o6) \ifracd{d}{d\,x}\,\mathrm{ln}\left(y-x^2-1\right)-y^2

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.

Resources