I have the following maxima code:
declare(p, real)$
declare(q, real)$
declare(m, real)$
is(-(4*p^2*q^2)/m^2-(4*p^4)/m^2 < 0);
This evaluates to unknown. Can I declare that p,q and m are positive real numbers?
Short answer to the question
Putting #Michael O.'s comment into the form of an answer:
The assume function can be used to set predicates on variables, in particular to tell maxima that a number is positive (this is also useful for calculating some integrals with integrate)
assume(p>0,q>0,m>0);
is(-(4*p^2*q^2)/m^2-(4*p^4)/m^2 < 0);
Some more functions for managing predicates
The list of predicates can be displayed using the facts function and removed using the forget function
kill(all); /*Clears many things, including facts*/
assume(a>0,b>0,c>0)$ /*Learn facts*/
facts();
forget(b>0)$ /*Forget one fact*/
facts();
forget(facts())$ /*Forget all known facts*/
facts();
Example of usage of assume with integrate function
Some mathematical results depends on e.g. the sign of some parameters. In particular, it is the case of some integrals.
(%i0) print("Without predicates: Maxima prompts the user")$
kill(all)$
L : sqrt(1 - 1/(R^2))$
facts();
integrate(x,x,0,L);
print("With predicates: Maxima does not need to prompt the user because it already knows the answer")$
kill(all)$
assume(R>0)$
L : sqrt(1 - 1/(R^2))$
facts();
integrate(x,x,0,L);
Without predicates: Maxima prompts the user
(%o0) []
Is "R" positive or negative? positive;
(%o1) (R^2-1)/(2*R^2)
With predicates: Maxima does not need to prompt the user because it already knows the answer
(%o2) [R>0]
(%o3) (R^2-1)/(2*R^2)
Related
I wonder if there is any way to make functions defined within the main function be local, in a similar way to local variables. For example, in this function that calculates the gradient of a scalar function,
grad(var,f) := block([aux],
aux : [gradient, DfDx[i]],
gradient : [],
DfDx[i] := diff(f(x_1,x_2,x_3),var[i],1),
for i in [1,2,3] do (
gradient : append(gradient, [DfDx[i]])
),
return(gradient)
)$
The variable gradient that has been defined inside the main function grad(var,f) has no effect outside the main function, as it is inside the aux list. However, I have observed that the function DfDx, despite being inside the aux list, does have an effect outside the main function.
Is there any way to make the sub-functions defined inside the main function to be local only, in a similar way to what can be made with local variables? (I know that one can kill them once they have been used, but perhaps there is a more elegant way)
To address the problem you are needing to solve here, another way to compute the gradient is to say
grad(var, e) := makelist(diff(e, var1), var1, var);
and then you can say for example
grad([x, y, z], sin(x)*y/z);
to get
cos(x) y sin(x) sin(x) y
[--------, ------, - --------]
z z 2
z
(There isn't a built-in gradient function; this is an oversight.)
About local functions, bear in mind that all function definitions are global. However you can approximate a local function definition via local, which saves and restores all properties of a symbol. Since the function definition is a property, local has the effect of temporarily wiping out an existing function definition and later restoring it. In between you can create a temporary function definition. E.g.
foo(x) := 2*x;
bar(y) := block(local(foo), foo(x) := x - 1, foo(y));
bar(100); /* output is 99 */
foo(100); /* output is 200 */
However, I don't this you need to use local -- just makelist plus diff is enough to compute the gradient.
There is more to say about Maxima's scope rules, named and unnamed functions, etc. I'll try to come back to this question tomorrow.
To compute the gradient, my advice is to call makelist and diff as shown in my first answer. Let me take this opportunity to address some related topics.
I'll paste the definition of grad shown in the problem statement and use that to make some comments.
grad(var,f) := block([aux],
aux : [gradient, DfDx[i]],
gradient : [],
DfDx[i] := diff(f(x_1,x_2,x_3),var[i],1),
for i in [1,2,3] do (
gradient : append(gradient, [DfDx[i]])
),
return(gradient)
)$
(1) Maxima works mostly with expressions as opposed to functions. That's not causing a problem here, I just want to make it clear. E.g. in general one has to say diff(f(x), x) when f is a function, instead of diff(f, x), likewise integrate(f(x), ...) instead of integrate(f, ...).
(2) When gradient and Dfdx are to be the local variables, you have to name them in the list of variables for block. E.g. block([gradient, Dfdx], ...) -- Maxima won't understand block([aux], aux: ...).
(3) Note that a function defined with square brackets instead of parentheses, e.g. f[x] := ... instead of f(x) := ..., is a so-called array function in Maxima. An array function is a memoizing function, i.e. if f[x] is called two or more times, the return value is only computed once, and then returned every time thereafter. Sometimes that's a useful optimization when the domain of the function comprises a finite set.
(4) Bear in mind that x_1, x_2, x_3, are distinct symbols, not related to each other, and not related to x[1], x[2], x[3], even if they are displayed the same. My advice is to work with subscripted symbols x[i] when i is a variable.
(5) About building up return values, try to arrange to compute the whole thing at one go, instead of growing the result incrementally. In this case, makelist is preferable to for plus append.
(6) The return function in Maxima acts differently than in other programming languages; it's a little hard to explain. A function returns the value of the last expression which was evaluated, so if gradient is that last expression, you can just write grad(var, f) := block(..., gradient).
Hope this helps, I know it's obscure and complex. The Maxima programming language was not designed before being implemented, and some of the decisions are clearly questionable at the long interval of more than 50 years (!) later. That's okay, they were figuring it out as they went along. There was not a body of established results which could provide a point of reference; the original authors were contributing to what's considered common knowledge today.
In Maxima, I am trying to simplify the expression
sqrt(1 - sin(x)) * sqrt(1 + sin(x))
to yield
cos(x)
I properly restricted the definition of x
declare(x, real) $
assume(x > 0, x < %pi/2) $
and tried several simplification commands including radcan, trigsimp, trigreduce and trigexpand, but without any success. How can this be done?
Try trigsimp(rootscontract(expr))
The restrictions you assert do not uniquely determine the simplified result you request.
It would seem both harmless and obviously unnecessary to declare or assume the following:
declare(9, real)
assume(9>0)
and yet, sqrt(9) is still the set {-3, +3}, mathematically speaking, as opposed to "what I learned in 6th grade".
Stavros' suggestion give |cos(x)|, which is not quite what the original questioner wanted.
Another way of getting the same result, one which may more explicitly exhibit the -in general falseness - of the result, is to square and then use the semi-bogus sqrt, that attempts to pick the positive answer.
trigsimp (sqrt(expand(expr^2)));
If you think this is a way of simplifying expr, note that it changes -3 to 3.
I am surprising to notice that it is somehow difficult to obtain a correct fit of interaction function from gam().
To be more specific, I want to estimate an additive function:
y=m_1(x)+m_2(z)+m_{12}(x,z)+u,
where m_1(x)=x^2, m_2(z)=z^2,m_{12}(x,z)=xz. The following code generate this model:
test1 <- function(x,z,sx=1,sz=1) {
#--m1(x) function
m.x<-x^2
m.x<-m.x-mean(m.x)
#--m2(z) function
m.z<-z^2
m.z<-m.z-mean(m.z)
#--m12(x,z) function
m.xz<-x*z
m.xz<-m.xz-mean(m.xz)
m<-m.x+m.z+m.xz
return(list(m=m,m.x=m.x,m.z=m.z,m.xz=m.xz))
}
n <- 1000
a=0
b=2
x <- runif(n,a,b)/20
z <- runif(n,a,b)
u <- rnorm(n,0,0.5)
model<-test1(x,z)
y <- model$m + u
So I use gam() by fitting the model as
b3 <- gam(y~ ti(x) + ti(z) + ti(x,z))
vis.gam(b3);title("tensor anova")
#---extracting basis matrix
B.f3<-model.matrix.gam(b3)
#---extracting series estimator
b3.hat<-b3$coefficients
Question: when I plot the estimated function by gam()above against its true function, I end up with
par(mfrow=c(1,3))
#---m1(x)
B.x<-B.f3[,c(2:5)]
b.x.hat<-b3.hat[c(2:5)]
plot(x,B.x%*%b.x.hat)
points(x,model$m.x,col='red')
legend('topleft',c('Estimate','True'),lty=c(1,1),col=c('black','red'))
#---m2(z)
B.z<-B.f3[,c(6:9)]
b.z.hat<-b3.hat[c(6:9)]
plot(z,B.z%*%b.z.hat)
points(z,model$m.z,col='red')
legend('topleft',c('Estimate','True'),lty=c(1,1),col=c('black','red'))
#---m12(x,z)
B.xz<-B.f3[,-c(1:9)]
b.xz.hat<-b3.hat[-c(1:9)]
plot(x,B.xz%*%b.xz.hat)
points(x,model$m.xz,col='red')
legend('topleft',c('Estimate','True'),lty=c(1,1),col=c('black','red'))
However, the function estimate of m_1(x) is largely different from x^2, and the interaction function estimate m_{12}(x,z) is also largely different from xz defined in test1 above. The results are the same if I use predict(b3).
I really can't figure it out. Can anybody help me out by explaining why the results end up with this? Greatly appreciate it!
First, the problem of the above issue is not due to the package, of course. It is closely related to the identification conditions of the smooth functions. One common practice is to impose the assumptions that E(mj(.))=0 for all individual function j=1,...,d, and E(m_ij(x_i,x_j)|x_i)=E(m_ij(x_i,x_j)|x_j)=0 for i not equal to j. Those conditions require one to employ centered basis function in series estimator, which has been done already in GAM package. However, in my case above, function m(x,z)=x*z defined in test1 does not satisfy the above identification assumptions, since the integral of x*z with respect to either x or z is not zero when x and z have range from zero to two.
Furthermore, series estimator allows the individual and interaction function to be identified if one impose m(0)=0 or m(0,x_j)=m(x_i,0)=0. This can be readily achieved if we center the basis function around zero. I have tried both cases, and they work well whenever DGP satisfies the identification conditions.
I have a fairly large expression that involves a lot of subexpressions of the form (100*A^3 + 200*A^2 + 100*A)*x or (-A^2 - A)*y or (100*A^2 + 100*A)*z
I know, but I don't know how to tell Maxima this, that it in this case is valid to make the approximation A+1 ~ A, thereby effectively removing anything but the highest power of A in each coefficient.
I'm now looking for functions, tools, or methods that I can use to guide Maxima in dropping various terms that aren't important.
I have attempted with subst, but that requires me to specify each and every factor separately, because:
subst([A+1=B], (A+2)*(A+1)*2);
subst([A+1=B], (A+2)*(A*2+2));
(%o1) 2*(A+2)*B
(%o2) (A+2)*(2*A+2)
(that is, I need to add one expression for each slightly different variant)
I tried with ratsimp, but that's too eager to change every occurrence:
ratsubst(B, A+1, A*(A+1)*2);
ratsubst(B, A+1, A*(A*2+2));
(%o3) 2*B^2-2*B
(%o4) 2*B^2-2*B
which isn't actually simpler, as I would have preferred the answer to have been given as 2*B^2.
In another answer, (https://stackoverflow.com/a/22695050/5999883) the functions let and letsimp were suggested for the task of substituting values, but I fail to get them to really do anything:
x:(A+1)*A;
let ( A+1, B );
letsimp(x);
(x)A*(A+1)
(%o6) A+1 --\> B
(%o7) A^2+A
Again, I'd like to approximate this expression to A^2 (B^2, whatever it's called).
I understand that this is, in general, a hard problem (is e.g. A^2 + 10^8*A still okay to approximate as A^2?) but I think that what I'm looking for is a function or method of calculation that would be a little bit smarter than subst and can recognize that the same substitution could be done in the expression A^2+A as in the expression 100*A^2+100*A or -A^2-A instead of making me create a list of three (or twenty) individual substitutions when calling subst. The "nice" part of the full expression that I'm working on is that each of these A factors are of the form k*A^n*(A+1)^m for various small integers n, m, so I never actually end up with the degenerate case mentioned above.
(I was briefly thinking of re-expressing my expression as a polynomial in A, but this will not work as the only valid approximation of the expression (A^3+A^2+A)*x + y is A^3*x + y -- I know nothing about the relative sizes of x and y.
We are giving students some exercises, where their solutions are evaluated with maxima.
The answer involves the unit step function. The evaluation in maxima seems to go okay, except that there seems to be missing some algebraic rules on the unit_step functions.
For example is(unit_step(x)*unit_step(x) = unit_step(x)) evaluates to false. It is quite unlikely that the student gives the answer in such a form, but still we don't want to have the possibility that the student gives a good answer, that is evaluated as incorrect.
Below is a screenshot of an answer we try to evaluate with maxima involving the unit_step function (that we defined as u):
Maxima doesn't know much about unit_step at present (circa Maxima 5.41). This is just a shortcoming, there's no reason for it, except that nobody has gotten around to doing the work. That said, it's not too hard to make some progress.
The simplifier for multiplication merges identical terms into powers:
(%i3) unit_step(x)*unit_step(x);
2
(%o3) unit_step (x)
So let's define a simplifier rule which reduces positive powers of unit_step. (I was going to say positive integer powers, but a moment's thought shows that the same identity holds for noninteger positive powers as well.)
(%i4) matchdeclare (aa, lambda ([e], e > 0)) $
(%i5) matchdeclare (xx, all) $
(%i6) tellsimpafter (unit_step(xx)^aa, unit_step(xx));
(%o6) [^rule1, simpexpt]
Let's try it.
(%i7) unit_step(x)*unit_step(x);
(%o7) unit_step(x)
(%i8) is (unit_step(x)*unit_step(x) = unit_step(x));
(%o8) true
(%i9) unit_step(t - 5)^(1/4);
(%o9) unit_step(t - 5)
(%i10) assume (m > 0);
(%o10) [m > 0]
(%i11) unit_step(2*u + 1)^m;
(%o11) unit_step(2 u + 1)
So far, so good. Of course this is just one identity and there are others that could be useful. Since this rule is not built-in, one would have to load that definition in order to make use of it; that would be bothersome if you intend for others to use this.
For the record, the only simplification for unit_step which I found in the Maxima source code is in share/contrib/integration/abs_integrate.mac, which contains a function unit_step_mult_simp, which applies the identity unit_step(a)*unit_step(b) --> unit_step(min(a, b)).