Maple error - "illegal use of a formal parameter" - maple

I'M TRYIN TO CREATE A PROGRAM USING MAPLE FOR GAUSSING ELIMINATION BUT I KEEP GETTING THIS ERROR
Gauss := proc (n::posint, A::matrix, c::Vector)
local a, i, k, j, p;
with(MTM):
n := linalg[rowdim](A);
if det(A) = 0 then print('matrice*doit*etre*caree')
else if det(A) <> 0
then a := `<|>`(A, c);
for k to n-1 do
for i from k+1 to n do
if a[i, i] = 0 then swaprow(a, k, i)
else p = a[i, k]/a[k, k];
for j from k+1 to n+1 do a[i, j] = a[i, j]-p*a[k, j]
end do;
end if;
end do;
end do;
else print('rien')
end if; end if; end proc;
Error, (in Gauss) illegal use of a formal parameter

restart;
Gauss := proc(A::Matrix, c::Vector)
local a, i, k, j, m, n, p;
n := linalg[rowdim](A);
m := linalg[coldim](A);
if m <> n then
print("matrice doit etre caree");
else
a := `<|>`(A, c);
for k to n-1 do
for i from k+1 to n do
if a[i, i] = 0 then
a := linalg[swaprow](a, k, i);
else
p := a[i, k]/a[k, k];
for j from k to n+1 do
a[i, j] := a[i, j]-p*a[k, j];
end do;
end if;
end do;
end do;
end if;
return a;
end proc:
c := Vector([2, 3, 4]);
A := Matrix(3, 3, [4, 1, 2, 3, 6, 5, 2, 1, 9]);
Gauss(A, c);
LinearAlgebra:-LUDecomposition(<A|c>, output=U);
There were quite a few mistakes, so let's hope I get most of them.
I didn't bother doing 7. You should do it.
You cannot use with inside a procedure.
Your code uses commands from thelinalg
package, not the MTM package.
Ideally you'd use Matrix&Vector&LinearAlgebra
(instead of your mix of matrix&Vector&linalg(.
Your procedure has n as one of its
parameters, but inside it you also try to
assign a value to n, the argument for which
you passed in as the number 3. That's where
your error message is coming from. You can't
do that.
Several of you lines have just = instead of
:= for assignments. The = does nothing.
The test against det(A)=0 is wrong is wrong
in several ways. I'll just say that it doesn't
actually test whether the A is square.
Compare the row & column dimensions if you
want to test that A is square.
You should be using LinearAlgebra
equivalents instead of the linalg commands
commands swaprow, coldim.
You forgot to have your procedure actually
return the Matrix a.
When your code calls swaprow is was not
actually updating a. It was just throwing
way the result.
It's a sin to not indent your code. It will
lead you to overlook mistakes.

Related

figure out math formula for spaces in pascal diamond project

How is it going guys ?
I've written a program that "draws" diamond in the command line (it's a part of my homework). For spaces inside the diamond I was given a formula "1 + 2(k-2) or 2k -3 , where k is line number", but I don't understand how this formula was created. Could anyone explain it ?
program diamond;
var
n, k, h, i: integer;
begin
repeat
write('Enter the diamond''s height (positive odd): ');
readln(h);
until (h > 0) and (h mod 2 = 1);
n := h div 2;
for k := 1 to n + 1 do
begin
for i := 1 to n + 1 - k do
write(' ');
write('*');
if k > 1 then
begin
for i := 1 to 2*k - 3 do
write(' ');
write('*')
end;
writeln
end;
for k := n downto 1 do
begin
for i := 1 to n + 1 - k do
write(' ');
write('*');
if k > 1 then
begin
for i := 1 to 2*k - 3 do
write(' ');
write('*')
end;
writeln
end
end.
I've already figured it out. It's a simple, but modified arithmetic progression An=A1-d(n-2). Usually we would use (n-1), but because we need to substract 2 stars from each line (starting from the second one, as this formula works for k>1), we use (n-2)

Modelica - iterator with exception?

Slightly generalised example:
How do I make a for loop with exceptions when I define model equations?
The following works:
model Test
Real[9] q;
equation
q[2] = 1.2;
q[4] = 1.4;
for i in {1,3,5,6,7,8,9} loop
q[i] = 0;
end for;
end Test;
But I would rather like to write something like:
model Test
Real[9] q;
equation
q[2] = 1.2;
q[4] = 1.4;
for i in 1:9 and not in {2,4} loop
q[i] = 0;
end for;
end Test;
Is this possible?
This should be possible, as long as you make sure to have an equation for every unknown.
Probably not the perfect solution, but actually pretty readable:
model LoopException
Real[9] q;
equation
q[2] = 1.2;
q[4] = 1.4;
for i in 1:9 loop
if Modelica.Math.Vectors.find(i, {2, 4}) == 0 then
q[i] = 0;
end if;
end for;
end LoopException;
As an alternative, you could also try to write an "Array Constructor with Iterators" (Modelica Language Spec. Sec. 10.4.1), but that probably gets a bit messy...
With 2 helper functions you can easily emulate what you want:
model Test
Real[9] q;
equation
q[2] = 1.2;
q[4] = 1.4;
for i in allExcept(1:9, {2,4}) loop
q[i] = 0;
end for;
end Test;
Here are the functions you need for that:
function contains
"Check if vector v contains any element with value e"
input Integer vec[:];
input Integer e;
output Boolean result;
algorithm
result := false;
for v in vec loop
if v == e then
result := true;
break;
end if;
end for;
end contains;
function allExcept
"Return all elements of vector v which are not part of vector ex"
input Integer all[:];
input Integer ex[:];
output Integer vals[size(all, 1) - size(ex, 1)];
protected
Integer i=1;
algorithm
for v in all loop
if not contains(ex, v) then
vals[i] := v;
i := i + 1;
end if;
end for;
end allExcept;
Note that Modelica tools usually need to know the size of vectors during translation, especially here when you generate equations. Hence, the following line is required:
output Integer vals[size(all, 1) - size(ex, 1)];
It will fail when all or ex contain duplicate elements.
Therefore the model will not translate, if you try something like
for i in allExcept(1:3, {2, 2}) loop

How to plot experimental data at special points?

I have a set of experimental data (P), and I want to obtain plot "experimental vs predicted". In order to do so, I use another set of data which depend on P (Q), plot ScatterPlot, use appropriate fit, then obtain regression line, and use its coefficients in appropriate differential equation. Plot of P looks good, but I need to add there experimental data. For simplicity, I've used interval t=0..150.
How can I plot experimental data so that P(0) = Pvals[1], P(10)=Pvals[2], etc.? Besides, how can I distribute data (say, I have t=0..800 and want to plot Pvals so that P(0) = Pvals[1] and P(800) = Pvals[16])?
Pvals := [3.929, 5.308, 7.24, 9.638, 12.866, 17.069, 23.192, 31.433, 38.558, 50.156, 62.948,
75.996, 91.972, 105.711, 122.775, 131.669]:
for i to 15 do Qval[i] := .1*(Pvals[i+1]/Pvals[i]-1); end do:
Qvals := [seq(Qval[i], i = 1 .. 15), 0.144513895e-1]:
with(Statistics);
ScatterPlot(Pvals, Qvals, fit = [a*v^2+b*v+c, v], thickness = 3,
legend = [points = "Point data", fit = typeset("fit to a", 2^nd, "degree polynomial")]);
with(CurveFitting);
LeastSquares(Pvals, Qvals, v, curve = a*v^2+b*v+c);
de := diff(P(t), t) = (0.370152282598477e-1-0.272504103112702e-3*P(t))*P(t);
sol := dsolve({de, P(0) = 3.929}, P(t));
P := plot(rhs(sol), t = 0 .. 160);
I'm not sure that I entirely follow your methodology. But is this something like what you are trying to accomplish?
restart;
with(Statistics):
Pvals := [3.929, 5.308, 7.24, 9.638, 12.866, 17.069, 23.192, 31.433,
38.558, 50.156, 62.948, 75.996, 91.972, 105.711, 122.775, 131.669]:
for i to 15 do Qval[i] := .1*(Pvals[i+1]/Pvals[i]-1); end do:
Qvals := [seq(Qval[i], i = 1 .. 15), 0.144513895e-1]:
form := a*v^2+b*v+c:
CF := CurveFitting:-LeastSquares(Pvals, Qvals, v, curve = form);
CF := 0.0370152282598477 - 0.000272504103112702 v
-7 2
+ 5.60958249026713 10 v
Now I use CF in the DE (since I don't understand why you dropped the v^2 term),
#de := diff(P(t), t) = (0.370152282598477e-1-0.272504103112702e-3*P(t))*P(t);
de := diff(P(t), t) = eval(CF, v=P(t))*P(t);
d /
de := --- P(t) = \0.0370152282598477 - 0.000272504103112702 P(t)
dt
-7 2\
+ 5.60958249026713 10 P(t) / P(t)
I'll use the numeric option of the dsolve command, and obtain a procedure that computes P(t) for numeric t values.
sol := dsolve({de, P(0) = 3.929}, P(t), numeric, output=listprocedure ):
Pfunc := eval(P(t), sol);
Pfunc := proc(t) ... end;
Pfunc(0.0), Pvals[1];
3.92900000000000, 3.929
Now some rescaling (which, again, is my guess as to your goal),
endpt := fsolve(Pfunc(t)-Pvals[16]);
endpt := 135.2246055
Pfunc(endpt), Pvals[16];
131.669000003321, 131.669
plot(Pfunc(t), t=0 .. endpt, size=[500,200]);
a,b,N := 0.0, 800.0, nops(Pvals);
a, b, N := 0., 800.0, 16
Pfuncscaled := proc(t)
if not t::numeric then
return 'procname'(args);
end if;
Pfunc(t*endpt/b);
end proc:
Pfuncscaled(0), Pvals[1];
3.92900000000000, 3.929
Pfuncscaled(800), Pvals[N];
131.669000003321, 131.669
PLscaled := plot( Pfuncscaled(t), t=a .. b,
color=red, size=[500,200] );
Now to display the Pdata against 0 .. 800 as well,
V := Vector(N, (i)->a+(i-1)*(b-a)/(N-1)):
V[1], V[-1];
0., 800.0000000
Pdatascaled := plot( < V | Vector(Pvals) >,
color=blue, size=[500,200],
style=pointline, symbol=solidcircle );
And, displaying the rescaled data together with the rescaled procedure from dsolve,
plots:-display( PLscaled, Pdatascaled, size=[500,500] );

Need help in matrix dimension while converting from fortran to matlab

I have been working on a fortran code to convert it into the matlab. I am facing some issues with dimensioning! Following is the code which is giving me error
do 10 p = 1,m
d(p) = 0.d0
d(p) = x - x1(i,p) - x2(i,p) -
& double_sum(i,p,n,m,str,mot)
10 continue
double_sum = 0.d0
do 10 j = 1,m
do 20 k = 1,n
if (k .eq. i) then
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j)
endif
20 continue
10 continue
to which I converted it into matlab as:
for p=1:m
d(p)=0;
double_sum = 0;
for j=1:m
for k=1:n
if k==i
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j);
end
end
end
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
end
I am getting error of "index exceeding matrix".
The error line is for this part of my code:
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
So if I ignore double_sum(i,p,n,m,str,mot); this part, code runs perfectly.
I know the double_sum matrix is of 6D which looks suspicious to me, but I would like to have your support to successfully port this piece of fortran code.
Note:Asked the same question on matlab forum. But stackoverflow have more chances of people worked on fortran 77. Hence asking it here.
If the Fortran code in the Question is really everything, it may be a very rough snippet that explains how to calculate array d(:)
do 10 p = 1, m
d( p ) = x - x1( i, p ) - x2( i, p ) - double_sum( i, p, n, m, str, mot )
10 continue
with a function double_sum() defined by
double precision function double_sum( i, p, n, m, str, mot )
implicit none
integer, intent(in) :: i, p, n, m
double precision, intent(in) :: str( n, m ), mot( n, m, ?, ? )
integer j, k
double_sum = 0.d0
do 10 j = 1, m
do 20 k = 1, n
if (k .eq. i) then
else
double_sum = double_sum + mot( k, j, i, p ) * str( k, j )
endif
20 continue
10 continue
end
though it is definitely better to find the original Fortran source to check the context...(including how i and d(:) are used outside this code). Nevertheless, if we use the above interpretation, the corresponding Matlab code may look like this:
for p = 1:m
double_sum = 0;
for j = 1:m
for k = 1:n
if k == i
else
double_sum = double_sum + mot( k, j, i, p ) * str( k, j );
end
end
end
d( p ) = x - x1( i, p ) - x2( i, p ) - double_sum; % <--- no indices for double_sum
end
There is also a possibility that double_sum() is a recursive function, but because we cannot use the function name as the result variable (e.g. this page), it may be OK to exclude that possibility (so the Fortran code has two scopes, as suggested by redundant labels 10).
There is an error in your loops. The fortran code runs one loop over p=1:m, whose end is marked by the continue statement. Then, two nested loops over j and k follow.
Assuming, you know the size of all your arrays beforehand and have initialized them to the correct size (which may not be the case given your error statement) this is more along the lines of the fortran example you posted.
d = zeros(size(d));
for p=1:m
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
end
% add a statement here to set all entries of double sum to zero
double_sum = zeros(size(double_sum))
for j=1:m
for k=1:n
if k==i
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j);
end
end
end
It is a little hard to give advice without knowledge of more parts of the code. are mot and str and double_sum functions? Arrays? The ambiguous choice of brackets in those two languages are hardly OPs fault, but make it necessary to provide further input.

how to write a procedure to multiply two matrices using maple

Visit http://www.mapleprimes.com/questions/35644-Multiply-2-Matrices-In-Maple-Using-A-Procedure
restart:
mmm:=proc(a::Matrix,b::Matrix)
local c, i, j, k, m, n, p;
(m,n,p):=op([1,1],a), op([1,2],b), op([1,2],a);
if op([1,1],b) <> p then error "incompatible dimensions"; end if;
c:=Matrix(m,n);
for i from 1 to m do
for j from 1 to n do
c[i,j] := add(a[i,k]*b[k,j],k=1..p);
end do;
end do:
c;
end proc:
a:=LinearAlgebra:-RandomMatrix(2,3):
b:=LinearAlgebra:-RandomMatrix(3,5):
mmm(a,b);
a.b; # check
mmm(a,a^%T);
a.a^%T; # check
mmm(b,a); # test for dimension mismatch
b.a; # test for dimension mismatch
a:=LinearAlgebra:-RandomMatrix(33,33):
b:=LinearAlgebra:-RandomMatrix(33,33):
LinearAlgebra:-Norm(a.b - mmm(a,b));