Is there some way to tell maxima that an expression is always positive? Here is an example snippet that causes maxima to ask the question for the expression sin(a)*x:
declare([a,x,y],real);
ca: cos(a) = (x / (sqrt(x*x + y*y)));
a1: solve(ca,a)[1];
solve(a1,y);
You can use assume. From Maxima's own documentation:
-- Function: assume (, ..., )
Adds predicates , ..., to the current context.
If a predicate is inconsistent or redundant with the predicates in
the current context, it is not added to the context. The context
accumulates predicates from each call to `assume'.
`assume' returns a list whose elements are the predicates added to
the context or the atoms `redundant' or `inconsistent' where
applicable.
The predicates , ..., can only be expressions
with the relational operators `=' and `>'.
Predicates cannot be literal equality `=' or literal inequality
`#' expressions, nor can they be predicate functions such as
`integerp'.
Compound predicates of the form ` and ... and '
are recognized, but not ` or ... or '. `not
' is recognized if is a relational predicate.
Expressions of the form `not ( and )' and `not
( or )' are not recognized.
Maxima's deduction mechanism is not very strong; there are many
obvious consequences which cannot be determined by `is'. This is
a known weakness.
`assume' evaluates its arguments.
See also `is', `facts', `forget', `context', and `declare'.
Examples:
(%i1) assume (xx > 0, yy < -1, zz >= 0);
(%o1) [xx > 0, yy < - 1, zz >= 0]
(%i2) assume (aa < bb and bb < cc);
(%o2) [bb > aa, cc > bb]
(%i3) facts ();
(%o3) [xx > 0, - 1 > yy, zz >= 0, bb > aa, cc > bb]
(%i4) is (xx > yy);
(%o4) true
(%i5) is (yy < -yy);
(%o5) true
(%i6) is (sinh (bb - aa) > 0);
(%o6) true
(%i7) forget (bb > aa);
(%o7) [bb > aa]
(%i8) prederror : false;
(%o8) false
(%i9) is (sinh (bb - aa) > 0);
(%o9) unknown
(%i10) is (bb^2 < cc^2);
(%o10) unknown
'assume' works when there is a space either side of the relational operator. In other words in my instance: assume(L>0) does not work, but assume(L > 0) does work!
Related
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
I have the logistic map function in Maxima like so:
F(x,r,n):= x[n]=r*x[n-1]*(1-x[n-1]);
And when I input the correct variables it gives me the answer to, for example, x[0]:
(%i15) n:0$
x[n-1]:[0.1]$
F(x, r:3, n);
(%o15) x[0]=[0.27]
However, this answer does not stay memorized and when I enter x[0] I get
x[0];
(%o5) x[0]
How do I write a function that will calculate x[n] for me and store it in memory, so I can use it later? I am trying to make a bifurcation diagram for the logistic map without using any black boxes, i.e., the orbits functions.
Thank you!
There are different ways to go about it. One straightforward way is to create a list and then iterate, computing its elements one by one. E.g.:
(%i4) x: makelist (0, 10);
(%o4) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
(%i5) x[1]: 0.1;
(%o5) 0.1
(%i6) r: 3;
(%o6) 3
(%i7) for i:2 thru 10 do x[i]: r * x[i - 1] * (1 - x[i - 1]);
(%o7) done
(%i8) x;
(%o8) [0.1, 0.2700000000000001, 0.5913000000000002,
0.7249929299999999, 0.5981345443500454, 0.7211088336156269,
0.603332651091411, 0.7179670896552621, 0.6074710434816448,
0.7153499244388992]
Note that : is the assignment operator, not =.
We have an online platform where we use maxima on the backend to give feedback on the answers that the student give.
Say that the solution of a polynomial long division is the following function:
sol: 3+(2+4*x)/(3*x^2+2*x+8);
Let's say that the student gives the answer:
ans: 3 +(3-5*x)/(3x^2+2*x+8)
We then want to give feedback along the lines.
Your answer is indeed of the following form:
The constant s is correct, but you didn't choose the right linear function r(x).
I try to implement this feedback in the following way:
ans: 3 +(3-5*x)/(3x^2+2*x+8);
remvalue(a,b,c,d);
matchdeclare([a,b,c,d], constantp);
defmatch(match, d+ (a*x+b)/(3*x^2+2*x+8));
match(ans);
However, defmatch doesn't seem to be able to match this. Is there any other function I can use for matching quotient function like this?
It does work in more simple scenarios:
ans: (3-5*x)/(3*x^2+2*x+8);
remvalue(a,b,c);
matchdeclare([a,b,c], constantp);
defmatch(match, (a*x+b)/(3*x^2+2*x+8));
match(ans);
If the problems are all polynomial division, maybe you can use the divide function which returns the quotient and remainder and then verify that the student's input is the same as quotient + remainder/divisor.
As to matching quotient + remainder/divisor, defmatch might not be powerful enough because it is mostly (although not entirely) looking for formal matches, and it can't, in many cases, detect expressions which are equivalent but formally different.
Let me think about how to implement a match function for this problem. Perhaps others have a suggestion too.
EDIT: Here's a way to match such expressions. I'll separate a ratio of polynomials from other terms. If there is one ratio term, and all the other terms are a polynomial, then the pattern you want is matched.
I've made use of at least one obscure but useful and even comprehensible feature of matching of "+" expressions. Since "+" is commutative, the pattern matcher sweeps up all the arguments which match the first predicate that is attempted, then sweeps through with the second, and so, if there are more than two predicts. If any pattern matching variable is declared to match all, it matches all arguments and there are none left. The pattern variables will be attempted in reverse order, so aa will be processed last. The effect is to divide a "+" expression into terms which match a stated predicate and a catch-all for everything else. This is made use of in %i7.
(%i2) matchdeclare (pp, lambda ([e], polynomialp (e, [pvar]))) $
(%i3) matchdeclare (qq, lambda ([e], diff (e, pvar) # 0 and polynomialp (e, [pvar]))) $
(%i4) defmatch (match_pratio, pp/qq, pvar) $
(%i5) matchdeclare (aa, all) $
(%i6) matchdeclare (rr, lambda ([e], match_pratio (e, pvar) # false)) $
(%i7) defmatch (match_pratio_plus_remainder, rr + aa, pvar) $
(%i8) match_foo (e, pvar) :=
block ([aa, pp, qq, rr],
if match_pratio (e, pvar) # false
then [0, pp, qq, pp/qq]
elseif match_pratio_plus_remainder (e, pvar) # false
then if polynomialp (aa, [pvar]) and op(rr) # "+"
then [aa, pp, qq, rr]) $
Here are some examples that match:
(%i9) match_foo (u^2/2 - 3*u + 1 + (u - 1)/(u^2 + u - 1), u);
2
u 2 u - 1
(%o9) [-- - 3 u + 1, u - 1, u + u - 1, ----------]
2 2
u + u - 1
(%i10) match_foo (u^2/2 - 3*u + 1 - 2*(u - 1)/(u^2 + u - 1), u);
2
u 2 2 (u - 1)
(%o10) [-- - 3 u + 1, - 2 (u - 1), u + u - 1, - ----------]
2 2
u + u - 1
(%i11) match_foo (u^2/2 - 3*u + 1 - 2/(u^2 + u - 1), u);
2
u 2 2
(%o11) [-- - 3 u + 1, - 2, u + u - 1, - ----------]
2 2
u + u - 1
(%i12) match_foo (1 - 2/(u^2 + u - 1), u);
2 2
(%o12) [1, - 2, u + u - 1, - ----------]
2
u + u - 1
(%i13) match_foo (- 2/(u^2 + u - 1), u);
2 2
(%o13) [0, - 2, u + u - 1, - ----------]
2
u + u - 1
Here are some examples that don't match: two polynomial ratio terms, no polynomial ratio, and a nonpolynomial term.
(%i14) match_foo (1/u - 2/(u^2 + u - 1), u);
(%o14) false
(%i15) match_foo (1 - (u^2 + u - 1)/2, u);
(%o15) false
(%i16) match_foo (sin(u) - 2/(u^2 + u - 1), u);
(%o16) false
SECOND EDIT: I think I've misnamed match_pratio_plus_remainder, it should probably be match_remainder_plus_quotient. Oh well.
The following integral does is not evaluated by Maxima:
integrate(charfun(x<1/2), x, 0, 1);
Is there a different trick to make it work, or is it simply un-implemented?
The share package abs_integrate can integrate some expressions containing signum, abs, and unit_step. In this case you can write charfun(x < 1/2) in terms of signum(1/2 - x) and then abs_integrate can handle it.
You'll need to load abs_integrate. Note that abs_integrate modifies the behavior of integrate; there isn't a separate abs_integrate function to call.
(%i2) load (abs_integrate) $
(%i3) integrate (signum (1/2 - x), x, 0, 1);
(%o3) 0
(%i4) integrate (signum (1/2 - x), x, -1, 1);
(%o4) 1
(%i5) foo (e) := (1 + signum(e))/2;
1 + signum(e)
(%o5) foo(e) := -------------
2
(%i6) integrate (foo (1/2 - x), x, 0, 1);
1
(%o6) -
2
(%i7) integrate (foo (1/2 - x), x, -1, 1);
3
(%o7) -
2
Note that foo corresponds to charfun here.
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.