How to properly substitute a value to the variable used in formula in wxMaxima? - maxima

I calculated a velocity vector and its module from the equations of motion of a point in wxMaxima:
x:3*sin(4*t);
y:2*cos(4*t);
r:[x,y];
v:diff(r,t,1);
v_mod:sqrt(v.v);
Now I would like to calculate the velocity for t=5. How can I do this? When I add (t) and := everywhere, like this:
x(t):=3*sin(4*t);
y(t):=2*cos(4*t);
r(t):=[x(t),y(t)];
v(t):=diff(r(t),t,1);
v_mod(t):=sqrt(v(t).v(t));
and then add this line at the end:
v_mod(5);
I get the following error:
diff: second argument must be a variable; found 5
What am I doing wrong here?

The problem is that when you say v(5), you're getting diff(<something>, 5) and Maxima is complaining about that.
Try v(t) := at(diff(r(u), u), u = t) -- i.e., differentiate wrt a dummy variable u, and then evaluate that derivative at u equal to the argument t.
There are other ways to go about it. If at doesn't work for you, we can try something else.

Related

Obtaining numerical values from the mnewton function of the Maxima program

I use Maxima for calculations. I solve a system of nonlinear equations using Newton's method (mnewton()). I get the solution in the form of a list:
[[φ2=5.921818183272879,s=5.155870949147037]]
How to get the numerical value of the first (φ2) and second (s) unknown. If I substitute:
x: roz1[1][2]$
I get that x is equal to: s=5.155870949147037
What to do to make x equal to a numerical value only: 5.155870949147037
(without s=).
My code:
Maxima code
I have two ideas. (1) You can call rhs to return the right-hand side of an equation (likewise lhs for the left-hand side). E.g. rhs(s = 123) returns 123.
(2) You can call assoc to find the value associated with s (or any variable) in the mnewton results. E.g. assoc('s, [a = 1, b = 2, s = 3, u = 5]) returns 3.
I like (2) better since it is not necessary to know where in the list is the one that you're interested in.

Maxima: Is there any way to make functions defined within the main function be local, in a similar way to local variables?

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.

Provide custom gradient to drake::MathematicalProgram

Drake has an interface where you can give it a generic function as a constraint and it can set up the nonlinearly-constrained mathematical program automatically (as long as it supports AutoDiff). I have a situation where my constraint does not support AutoDiff (the constraint function conducts a line search to approximate the maximum value of some function), but I have a closed-form expression for the gradient of the constraint. In my case, the math works out so that it's difficult to find a point on this function, but once you have that point it's easy to linearize around it.
I know many optimization libraries will allow you to provide your own analytical gradient when available; can you do this with Drake's MathematicalProgram as well? I could not find mention of it in the MathematicalProgram class documentation.
Any help is appreciated!
It's definitely possible, but I admit we haven't provided helper functions that make it pretty yet. Please let me know if/how this helps; I will plan to tidy it up and add it as an example or code snippet that we can reference in drake.
Consider the following code:
from pydrake.all import AutoDiffXd, MathematicalProgram, Solve
prog = MathematicalProgram()
x = prog.NewContinuousVariables(1, 'x')
def cost(x):
return (x[0]-1.)*(x[0]-1.)
def constraint(x):
if isinstance(x[0], AutoDiffXd):
print(x[0].value())
print(x[0].derivatives())
return x
cost_binding = prog.AddCost(cost, vars=x)
constraint_binding = prog.AddConstraint(
constraint, lb=[0.], ub=[2.], vars=x)
result = Solve(prog)
When we register the cost or constraint with MathematicalProgram in this way, we are allowing that it can get called with either x being a float, or x being an AutoDiffXd -- which is simply a wrapping of Eigen's AutoDiffScalar (with dynamically allocated derivatives of type double). The snippet above shows you roughly how it works -- every scalar value has a vector of (partial) derivatives associated with it. On entry to the function, you are passed x with the derivatives of x set to dx/dx (which will be 1 or zero).
Your job is to return a value, call it y, with the value set to the value of your cost/constraint, and the derivatives set to dy/dx. Normally, all of this happens magically for you. But it sounds like you get to do it yourself.
Here's a very simple code snippet that, I hope, gets you started:
from pydrake.all import AutoDiffXd, MathematicalProgram, Solve
prog = MathematicalProgram()
x = prog.NewContinuousVariables(1, 'x')
def cost(x):
return (x[0]-1.)*(x[0]-1.)
def constraint(x):
if isinstance(x[0], AutoDiffXd):
y = AutoDiffXd(2*x[0].value(), 2*x[0].derivatives())
return [y]
return 2*x
cost_binding = prog.AddCost(cost, vars=x)
constraint_binding = prog.AddConstraint(
constraint, lb=[0.], ub=[2.], vars=x)
result = Solve(prog)
Let me know?

The tensor product ti() in GAM package gives incorrect results

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.

Maxima spline result not changing in loop

I'm trying to iterate over 2 parameters to get two splines for each pair. The code:
y_arr:[0.2487,0.40323333333333,0.55776666666667,0.7123]$
str_h_arr:[-0.8,-1.0,-1.2,-1.4]$
z_points:[0,0.1225,0.245,0.3675,0.49,0.6125,0.735,0.8575,0.98,1.1025,1.225,1.3475,1.47,
1.5925,1.715,1.8375,1.96,2.0825,2.205,2.26625,2.3275,2.3765,2.401,2.4255,2.43775,
2.4451,2.448775,2.45]$
length(a)$
length(b)$
load(interpol)$
for y_k:1 thru length(a) do (
for h_k:1 thru length(b) do (
y:y_arr[y_k],
str_h:str_h_arr[h_k],
bot_startpoints: [[-2.45,0],[0,y],[2.45,0]],
top_startpoints: [[-2.45,str_h_min],[0,y+str_h],[2.45,str_h_min]],
spline: cspline(bot_startpoints),
bot(x):=''spline,
print(bot(0))
)
);
//Part with top spline is skipped.
For all iterations output is now the same: 0.7123
What I want to get is two splines like in picture
Members of y_arr are y values in x=0, str_h_arr: height between splines in x=0.
So bot(0) should give me all values from y_arr.
If i don't use loop and just give this block values of y_k and h_k, it's working properly.
Can anybody point me to where I'm (or Maxima is) wrong with using loop with cspline?
The problem is that quote-quote (two single quotes, '') is applied only once, when it is read in input; it is not applied every time the expression in evaluated in the loop.
Looks like you need only to evaluate the spline at x = 0 and nothing else. So I'll suggest ev(spline, x=0) to evaluate it. You can also construct a lambda expression and evaluate that.
Here is the program after I've revised it as described above. Also, it is simpler and clearer to write for y in y_arr do (...) rather than making use of an explicit index for y_arr.
y_arr:[0.2487,0.40323333333333,0.55776666666667,0.7123]$
str_h_arr:[-0.8,-1.0,-1.2,-1.4]$
z_points:[0,0.1225,0.245,0.3675,0.49,0.6125,0.735,0.8575,0.98,1.1025,1.225,1.3475,1.47,
1.5925,1.715,1.8375,1.96,2.0825,2.205,2.26625,2.3275,2.3765,2.401,2.4255,2.43775,
2.4451,2.448775,2.45]$
load(interpol)$
for y in y_arr do (
for str_h in str_h_arr do (
bot_startpoints: [[-2.45,0],[0,y],[2.45,0]],
top_startpoints: [[-2.45,str_h_min],[0,y+str_h],[2.45,str_h_min]],
spline: cspline(bot_startpoints),
print (ev (spline, x=0))));
This is the output I get:
0.2487
0.2487
0.2487
0.2487
0.40323333333333
0.40323333333333
0.40323333333333
0.40323333333333
0.55776666666667
0.55776666666667
0.55776666666667
0.55776666666667
0.7123
0.7123
0.7123
0.7123

Resources