问题
I need to run the inner most for loop for some particular coordinate points that are complex number valued. However, I do not know the particular coordinate points. I am suppose to guess and check to get an answer. However that is tediuos. Hence I wanted to come up with nested for loops to do the work for me of checking for different values. When I try to run the code below I get a unterminating loop. Is there an error in my code?
for i from -100.0 to 100.0 do
for j from -100.0 to 100.0 do
for m from -100.0 to 100.0 do
for n from -100.0 to 100.0 do
X__0:=[i+j*I, m+n*I]
for K from 1 to 20 while evalf(abs(X[K-1][1]-X[K-2][1]),25)<>0 and evalf(abs(X[K-1][2]-X[K-2][2]),25)<>0
do
X[K]:=evalf(G(X[K-1][1], X[K-1][2]), 25)
end do;
Also if it is possible, Can I add a condition to the loop to not print solutions of X[k] which matches [16.19615242270663188058234, -1.928203230275509174109785] or [5.803847577293368119417661, 11.92820323027550917410978]?
回答1:
Clearly this relates to your earlier question. So I'll try to address both here.
You may be get the idea that a "thorough" search grid does better at finding most (or sometimes all) roots, but that a random process can often be faster at finding a smaller subset. However as more and more roots are found by the random method then the chances grow are that each newly generated random starting point will converge to a root already found.
You mentioned Maple 15 in one of your questions, so I ran the code below in 64bit Maple 15.01 for Windows.
I wrapped your basic steps inside a proc, to make things easier to use and (hopefully) understand.
I did not change your iteration scheme (which may be homework), but notice that it requires an initial point. Note that X__0 displays similarly to X[0] as pretty-printed 2D Math output, but they are not the same. This was a problem for your code on the Question, and also for the transcribed code on one of the examples in your other Question. I suggest you use 1D Maple Notation for your input mode if that is not entirely clear to you.
There's no need to use linalg[jacobian] which is deprecated. I adjusted to use VectorCalculus:-Jacobian.
restart;
f := (x-7)^4+(y-2)^2-100:
g := (x-11)^2+(y-5)^2-75:
G := unapply(convert(Vector([x,y])
-1/VectorCalculus:-Jacobian([f, g],[x, y]).Vector([f,g]),
list),x,y):
p := proc(X0::[complex(numeric),complex(numeric)], G)
local X, K;
X[0]:=X0;
for K to 30 while evalf[Digits+5](abs(X[K-1][1]-X[K-2][1])) <> 0
and evalf[Digits+5](abs(X[K-1][2]-X[K-2][2])) <> 0 do
X[K] := evalf[Digits+5](G(X[K-1][1], X[K-1][2]));
end do;
if not type(X[K-1],[complex(numeric),complex(numeric)]) then
error "nonnumeric results"; end if;
if K<29 then map(simplify@fnormal, evalf(X[K-1]));
else error "did not converge"; end if;
end proc:
p( [17, -2], G );
[9.879819419, -3.587502283]
p( [5, 11], G );
[5.127257522, 11.36481703]
p( [-1.0-11.*I, -2.0*I], G );
[7.144643342 - 2.930435630 I, -3.398413328 + 1.345239163 I]
Digits := 20:
p( [-1.0-11.*I, -2.0*I], G );
[7.1446433421702820770 - 2.9304356302329792484 I,
-3.3984133281207314618 + 1.3452391631560967251 I]
Equate([x,y],%);
[x = 7.1446433421702820770 - 2.9304356302329792484 I,
y = -3.3984133281207314618 + 1.3452391631560967251 I]
eval( [f,g], % );
[ -18 -18 -18 ]
[1 10 + 2 10 I, -1 10 + 0. I]
Digits := 10:
NN:=2: # This attempts (NN+1)^4 iterates
incx,incy:=5.0,5.0:
Sols:={}:
count:=0:
st := time():
for a from -NN to NN do
for b from -NN to NN do
for c from -NN to NN do
for d from -NN to NN do
count:=count+1;
try
cand := p( [a*incx+b*incy*I, c*incx+d*incy*I], G );
if not member(cand,{Sols}) then
Sols := Sols union {cand}; end if;
catch:
end try;
end do;
end do;
end do;
end do;
(time() - st)*'seconds', count*'attempts';
34.695 seconds, 625 attempts
nops( Sols );
8
sort( Sols );
{[3.867005122, 0.08874923598], [5.127257522, 11.36481703],
[5.721021477, 11.86530303], [9.879819419, -3.587502283],
[7.144643342 - 2.930435630 I, -3.398413328 + 1.345239163 I],
[7.144643342 + 2.930435630 I, -3.398413328 - 1.345239163 I],
[8.557804888 - 1.867139097 I, 13.53272982 - 0.5344031829 I],
[8.557804888 + 1.867139097 I, 13.53272982 + 0.5344031829 I]}
seq( eval( max(abs(f),abs(g)), Equate([x,y],xypoint) ), xypoint=Sols );
-8 -7 -8 -8 -8 -8
3 10 , 1 10 , 9 10 , 4 10 , 3.162277660 10 , 3.162277660 10 ,
-7 -7
1.019803903 10 , 1.019803903 10
randomize():
fgen := proc(a::numeric,b::numeric,i::nonnegint:=1)
seq(RandomTools:-Generate(float('range'=a..b,'digits'=5)),
ii=1..i);
end proc:
fgen(-100.0, 100.0); # Usage example, a random point
-26.41
randSols := {}:
A,B := 15, 15:
numattempts:=100:
st := time():
for s from 1 to numattempts do
try
cand := p( [fgen(-A,A)+fgen(-B,B)*I, fgen(-A,A)+fgen(-B,B)*I], G );
if not member(cand,{randSols}) then
randSols := randSols union {cand}; end if;
catch:
end try;
end do;
(time() - st)*'seconds', numattempts*'attempts';
5.756 seconds, 100 attempts
nops(randSols);
5
sort( randSols );
{[3.867005122, 0.08874923598],
[7.144643342 - 2.930435630 I, -3.398413328 + 1.345239163 I],
[7.144643342 + 2.930435630 I, -3.398413328 - 1.345239163 I],
[8.557804888 - 1.867139097 I, 13.53272982 - 0.5344031829 I],
[8.557804888 + 1.867139097 I, 13.53272982 + 0.5344031829 I]}
seq( eval( max(abs(f),abs(g)), Equate([x,y],xypoint) ), xypoint=randSols );
-8 -8 -8 -7 -7
3 10 , 3.162277660 10 , 3.162277660 10 , 1.019803903 10 , 1.019803903 10
回答2:
For each 'do' statement (i.e. loop) you need a corresponding 'end do', you only have one. Also you need to terminate statements (e.g. X__0:=[i+jI,m+nI]) with a colon or semicolon. E.g.,
for i from -100.0 to 100.0 do
for j from -100.0 to 100.0 do
for m from -100.0 to 100.0 do
for n from -100.0 to 100.0 do
X__0:=[i+j*I, m+n*I];
for K from 1 to 20 while evalf(abs(X[K-1][1]-X[K-2][1]),25)<>0 and evalf(abs(X[K-1][2]-X[K-2][2]),25) <>0 do
X[K]:=evalf(G(X[K-1][1], X[K-1][2]), 25);
end do;
end do;
end do;
end do;
end do;
end do;
Your code doesn't provide an initial definition of X[0] or define G, so it's hard otherwise to know what to suggest to improve things.
来源:https://stackoverflow.com/questions/35144017/nested-for-loops-for-maple-15