3

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

Rolf
  • 84
  • 6

2 Answers2

2

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
  • 6,671
  • 15
  • 15
0

@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.

  1. 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.

enter image description here

  1. 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.

enter image description here

It is indeed "x -> test(floor(x))".