Maple Error: final value in for loop must be numeric or character - maple

I have this simple procedure in Maple that I want to plot.
test:=proc(n)
local i,t;
for i from 1 to n do
t:=1;
od;
return t;
end:
The procedure itself works fine.
> test(19)
1
When I want to plot I get the following Error:
> plot(test(x),x=1..10)
Error, (in test) final value in for loop must be numeric or character
Please help

Maple's usual evaluation model is that arguments passed to commands are evaluated up front, prior to the computation done within the body of the command's own procedure.
So if you pass test(x) to the plot command then Maple will evaluate that argument test(x) up front, with x being simply a symbolic name.
It's only later in the construction of the plot that the plot command would substitute actual numeric values for that x name.
So, the argument test(x) is evaluated up front. But let's see what happens when we try such an up front evaluation of test(x).
test:=proc(n)
local i,t;
for i from 1 to n do
t:=1;
od;
return t;
end:
test(x);
Error, (in test) final value in for loop
must be numeric or character
We can see that your test procedure is not set up to receive a non-numeric, symbolic name such as x for its own argument.
In other words, the problem lies in what you are passing to the plot command.
This kind of problem is sometimes called "premature evaluation". It's a common Maple usage mistake. There are a few ways to avoid the problem.
One way is to utilize the so-called "operator form" calling sequence of the plot command.
plot(test, 1..10);
Another way is to delay the evaluation of test(x). The following use of so-called unevalution quotes (aka single right ticks, ie. apostrophes) delays the evaluation of test(x). That prevents test(x) from being evaluated until the internal plotting routines substitute the symbolic name x with actual numeric values.
plot('test(x)', x=1..10);
Another technique is to rewrite test so that any call to it will return unevaluated unless its argument is numeric.
test:=proc(n)
local i,t;
if not type(n,numeric) then
return 'procname'(args);
end if;
for i from 1 to n do
t:=1;
od;
return t;
end:
# no longer produces an error
test(x);
test(x)
# the passed argument is numeric
test(19);
1
plot(test(x), x=1..10);
I won't bother showing the actual plots here, as your example produces just the plot of the constant 1 (one).

#acer already talked about the technical problem, but your case may actually have a mathematical problem. Your function has Natural numbers as its domain, i.e. the set of positive integers {1, 2, 3, 4, 5, ...} Not the set of real numbers! How do you interpret doing a for-loop for until a real number for example Pi or sqrt(2) to 5/2? Why am I talking about real numbers? Because in your plot line you used plot( text(x), x = 1..10 ). The x=1..10 in plot is standing for x over the real interval (1, 10), not the integer set {1, 2, ..., 10}! There are two ways to make it meaningful.
Did you mean a function with integer domain? Then your plot should be a set of points. In that case you want a points-plot, you can use plots:-pointplot or adding the option style=point in plot. See their help pages for more details. Here is the simplest edit to your plot-line (keeping the part defininf test the same as in your post).
plot( [ seq( [n, test(n)], n = 1..10 ) ], style = point );
And the plot result is the following.
In your function you want the for loop to be done until an integer in relation with a real number, such as its floor? This is what the for-loop in Maple be default does. See the following example.
t := 0:
for i from 1 by 1 to 5/2 do
t := t + 1:
end do;
As you can see Maple do two steps, one for i=1 and one for i=2, it is treated literally as for i from 1 by 1 to floor(5/2) do, and this default behavior is not for every real number, if you replace 5/2 by sqrt(2) or Pi, Maple instead raise an error message for you. But anyway the fix that #acer provided for your code, plots the function "x -> test(floor(x))" in your case when x comes from rational numbers (and float numbers ^_^). If you change your code instead of returning constant number, you will see it in your plot as well. For example let's try the following.
test := proc(n)
local i,t:
if not type(n, numeric) then
return 'procname'(args):
end if:
t := 0:
for i from 1 to n do
t := t + 1:
end do:
return(t):
end:
plot(test(x), x=1..10);
Here is the plot.
It is indeed "x -> test(floor(x))".

Related

Fourier series graph generation from given coefficients an, bn in Matlab(Scilab)

I've calculated coefficients an, bn (100, T=2*pi) in c++ and checked that they are correct using few sources. Now i try to generate Fourier series graph for given example function in Scilab:
(x+2)*abs(cos(2*x*(x-pi/6)))
M=csvRead(filename, ";", [], 'double')
n=size(M,1)
for i = 1:n
A(i)=M(i)
B(i)=M(i + n)
end
function series=solution(x)
series=A(1)/2;
for i = 2:n
series=series+(A(i)*cos(i*x)+B(i)*sin(i*x));
end
endfunction
function series=solution2(x)
series=(x+2).*abs(cos(2.*x.*(x-%pi/6)));
endfunction
x = -%pi:%pi/100:%pi
plot2d(x, solution(x), 3)
x2 = -%pi:%pi/100:%pi
plot2d(x2, solution2(x2), 4)
Here is the result:
It clearly looks that tendency is ok but the beginning and the end of the period are wrong (reversed?). Do you see any issues in Scilab code? What could cause the problem - values in sin/cos in function solution(x)? Should i provide an, bn values and check for miscalculation there?
I don't know how did you calculated your A & B coefficients, but I assume that you used the usual notations to get the first line of the below formula:
Thus n starts from 1. Since Scilab starts vector indexing from 1, you correctly made your loop from 2, but forgot to compensate for this "offset".
Your function should be something like this:
function series=solution(x)
series=A(1)/2;
for i = 2:n
series=series+(A(i)*cos((i-1)*x)+B(i)*sin((i-1)*x));
end
endfunction
Since you didn't provided A & B, I can not check the result.
Additional note: Syntactically more correct if you explicitly define all input variables in a function, like this:
function series=solution(x,A,B)
This way you may be sure that your input is not changed somewhere else in the code.

Display expression and result of calculation in MuPad

Imagine I define two variables within a MuPad Notebook:
x:=2;
y:=5
For the product
z=x*y
I get displayed:
And if I use hold, I can get the expression:
z=hold(x*y)
But now I'd like to have both, the expression displayed and the result. The two options which appeared logical to me, do not worK:
z=hold(x*y);z
and
z=hold(x*y);eval(z);
How can I get displayed the expression AND the result?
If in two lines it would be alright, but I'd prefer in one line like:
z = x y = 10
I tried some combinations with print, expr2text, hold and _concat but couldn't find a convincing solution to get the desired result. But there is an explanation why the second line just returns z and not 10.
Assignment vs. Equation
z is the result in the second line because you didn't assign something to z yet. So the result says that z is z. In MuPad = is part of an expression. The assignment operator is := and therefore not the same as in Matlab. The only difference between them is the colon.
Writing an equation
For writing an equation, we use = as part of the expression. There is an equivalent function: _equal. So the following two lines generate the same result:
x+y = 2
_equal(x+y, 2)
Assign value to x
For an assignment we use := (in Matlab this would be only =). There is an equivalent function: _assign. So again, the following two lines generate the same result:
x := value
_assign(x, value)
Assign the equation x+y = 2 to eqn
Here we can clearly see the difference:
eqn := x+y = 2
_assign(eqn, _equal(x+y, 2))

Matlab: Command Line Inputs for an Eigenfunction Solver (Numerical Method)

I've got some code to numerically solve for eigenvectors:
function[efun,V,D] = solveeig(n,xmax,i)
for j=1:i
%The first and second derivative matrices
dd = 1/(xmax/n)^2*(-2*diag(ones(n,1))+diag(ones(n-1,1),1)+...
diag(ones(n-1,1),-1));
d = 1/(xmax/n)*((-1*diag(ones(n,1)))+diag(ones(n-1,1),1));
%solve for the eigenvectors
[V,D] = eig(-dd-2*d);
%plot the eigenvectors (normalized) with the normalized calculated
%eigenfunctions
x = linspace(0,xmax,n);
subplot(i,1,j);
plot(x,V(:,j)/sum(V(:,j)),'*');
hold on
efun = exp(-x).*sin(j*pi*x/xmax);
plot(x,efun/(sum(efun)),'r');
shg
end
end
i is supposed to be the first i eigenvectors, n is the dimension of the
matrices (the number of pieces we discretize x into), xmax is the upper limit of the range on which the fxn is defined.
I'm trying to run this from the command line (as: "solveeig # # #", where the number signs correspond to i, n, and xmax) but no matter what I seem to put in for i, n, and xmax, I get "For colon operator with char operands, first and last operands must be char."
What should I be writing on the command line to get this to run?
Using the command syntax interprets the arguments as strings
For fuller details see the documentation but in short:
Calling
myFun myVar1 6 myVar2
is equivalent to calling
myFun('myVar1','6','myVar2')
and not the desired1
myFun(myVar1,6,myVar2)
In the first cases the function will receive 3 strings (text)
In the second the function will receive the data stored in myVar1 myVar2 and the number 6
The specific error you received is caused by line 2 for j=1:i here i is a string. This error is a merely consequence of the way the function has been called, the line itself is fine2.
How to get it to work
Use function syntax: in the command window something like:
solveeig(n,xmax,i)
If command syntax is absolutely required ( and I can't think why it would be) the much less favourable alternative would be to parse the strings inputted in command syntax. To convert the numbers into numeric formats and use evalin/assignin on the passed variable names to pull variables in from the caller
1As mentioned in comments by patrik
2meaning it won't error, however i and j as variable names is another matter

Please explain the result from these commands

The code is
syms x;
v = #(x) (4 - x^2)^(1/2) - (2 - x)^(1/2)*(x + 2)^(1/2);
ezplot(v(x),[-2,2]);
which produce a plot
Should not v(x)
be zero for every x in [-2,2]?
If the idea is to replace "small" values in the output of your equation with zero, then some sort of if condition on the output data is needed. Unfortunately, you can't add an if to the anonymous function but you can do one of two things: define a standard function (in a program file) or wrap your anonymous function in another. The first way is more straightforward:
function [y] = v_func(x)
y = (4 - x.^2).^(1/2) - (2 - x).^(1/2).*(x + 2).^(1/2);
y(abs(y)<1e-10)=0;
end
The above performs the same calculation as before with second line of code replacing all values that are less than some tolerance (1e-10) with zero. Note how the equation is slightly different than your original one. It has been "vectorized" (see the use of the periods) to allow for an input vector to be evaluated rather than having to loop over each element in the vector. Note also that when we pass it to ezplot we must prefix the function name with the ampersand:
ezplot(#v_func,[-2,2]);
The second way requires wrapping your first anonymous function v in a couple of others (see anonymous functions and conditions). We start with your original function that has been vectorized:
v = #(x) (4 - x.^2).^(1/2) - (2 - x).^(1/2).*(x + 2).^(1/2);
and a (condition) function that replaces all values less than some tolerance with zero:
cond = #(y)(y*(1-(abs(y)<1e-10)))
We then wrap the two together as
func = #(x)cond(v(x))
so that the condition function evaluates the output of v. Putting it together with ezplot gives:
ezplot(func,[-2,2]);
and all output, as shown in the plot, should be zero.
The figure title will not be what you want, so it can be replaced with some variation of:
plotTitle = func2str(v);
title(strrep(plotTitle(5:end),'.','')); % as I don't want '#(x)' or periods to
% appear in the title
I've ignored the use of sym as I don't have the Symbolic Toolbox.

need explanation about a matlab code snippet about moran process

I am new to Matlab. I was reading this code snippet, but in some parts (marked with asterisks) I don't understand what it means, so if anybody could help would be very much appreciated
function [A1nmb] = moran(initsize, popsize)
% MORAN generates a trajectory of a Moran type process
% which gives the number of genes of allelic type A1 in a population
% of haploid individuals that can exist in either type A1 or type A2.
% The population size is popsize and the initial number of type A1
% individuals os initsize.
% Inputs: initsize - initial number of A1 genes
% popsize - the total population size (preserved)
if (nargin==0)
initsize=10;
popsize=30;
end
A1nmb=zeros(1,popsize);
A1nmb(1)=initsize;
**lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');
mu = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');**
x=initsize;
i=1;
while (x>1 & x<popsize+1)
if (lambda(x,popsize)/(lambda(x,popsize)+mu(x,popsize))>rand)
x=x+1;
A1nmb(i)=x;
else
x=x-1;
A1nmb(i)=x;
end;
i=i+1;
end;
nmbsteps=length(A1nmb);
***rate = lambda(A1nmb(1:nmbsteps-1),popsize) ...
+mu(A1nmb(1:nmbsteps-1),popsize);***
**jumptimes=cumsum(-log(rand(1,nmbsteps-1))./rate);**
jumptimes=[0 jumptimes];
stairs(jumptimes,A1nmb);
axis([0 jumptimes(nmbsteps) 0 popsize+1]);
The first line you marked
lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N');
creates something called an inline function. It is equivalent to defining a mathematical function. Example:
y = inline('x^2')
would allow you to do
>> y(2)
4
This immediately explains the second line you marked.
rate = lambda(A1nmb(1:nmbsteps-1),popsize) ...
+mu(A1nmb(1:nmbsteps-1),popsize);
will compute the value of the function lambda(x,N) at x = A1nmb(1:nmbsteps-1) and N = popsize.
I will say immediately here that you should take a look at anonymous functions, a different format used to accomplish the same as inline. Only, anonymous functions are generally better supported, and usually a lot faster than inline functions.
Then, for the final line,
jumptimes = cumsum(-log(rand(1,nmbsteps-1))./rate);
is a nested command. rand will create a matrix containing pseudorandom numbers, log is the natural logarithm ("ln"), and cumsum creates a new matrix, where all the elements in the new matrix are the cumulative sum of the elements in the input matrix.
You will find the commands doc and help very useful. Try typing
doc cumsum
or
help inline
on the Matlab command prompt. Try that again with the commands forming the previous statement.
As a general word of advice: spend an insane lot of time reading through the documentation. Really, for each new command you encounter, read about it and play with it in a sandbox until you feel you understand it. Matlab only becomes powerful if you know all its commands, and there are a lot to get to know.
It defines an inline function object. For example this
lambda = inline('(x-1).*(1-(x-1)./N)', 'x', 'N')
defines lambda as a function with 2 variables. When you call lambda(A,n) Matlab simply expands the function you define in the first string. Thus lambda(A,n) using the variables you provide in the function call. lambda(A,n) would will evaluate to:
(A-1).*(1-(A-1)./n)
it just expands the function using the parameters you supply. Take a look at this link for more specific details http://www.mathworks.co.uk/help/techdoc/ref/inline.html
The cumsum function just returns the cumulative sum of a matrix along a particular dimension. Say we call cumsum on a vector X, then the value at element i in the result is equal to the sum of elements in X from index 1 to i. For example X = [1 2 1 3] we would get
AA = cumsum(X);
we would have
AA = [1 3 5 8]
See this link for more details and examples http://www.mathworks.co.uk/help/techdoc/ref/cumsum.html