acer

32385 Reputation

29 Badges

19 years, 334 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

There are quite a few "lesser" problems with the code (loop summation instead of using the add command, inverting the same Matrix many times, repeated computation inside loops of sub-terms which don't depend on the loop-index, etc).

But as far as can see one of the primary efficiency problems is the cost of computing MatrixPower(V, 1/2) for V a float Matrix. Examination indicated to me that was the primary reason why Digits had to be set so high, and also that it was incurring a large port of the time cost.

It turns out that (at present) MatrixPower uses an inaccurate way to compute the square-root of a float Matrix, since (at present) it is just getting redirected to LinearAlgebra:-MatrixFunction to use a general purpose algorithm.

And the only thing that is being done with Vx the computed Matrix-square-root of V is obtaining and utilizing its eigenvalues and eigenvectors. Now, I don't know what your algorithm is supposed to accomplish overall. But for this particular subtask it seems to me that you could do away entirely with that MatrixPower(V, 1/2) call, and compute the eigenvectors and eigenvalues of the Matrix-square-root of V much more directly.

Here's my modification that makes this change. See the comments where the code changed.

FP3_modfidea.mw

This speeds things up enough that the loop-computations have changed from being relatively incidental to now contributing some of the greatest efficiency costs. So I suspect that the overall computation can be made faster still, but  I don't have time to work on it right now.

If there are still places where Digits needs to be raised, for higher N, then certainly that could be done. But such an increase to the working precision should probably only be done for the the duration of the subcomputations where it is necessary. Set Digits back down again, where it doesn't matter.

It's even possible that the eigen-solving might require a higher value for Digits as N gets large. But even then it'll be faster to utilize the simpler Eigenvectors(V) results than to call MatrixPower.

I'm going to log a bug report, that MatrixPower is not doing the best thing itself in this float Matrix example. Note that even if MatrixPower did the right thing here (accurately) it would still be the wrong thing to use: it'd make Maple compute eigenvectors twice, when once is adequate.

acer

I tried to speed it up, but a smoothish curve for u=0.1 .. 10 still took about an hour on my i7.

The plots look a lot smoother when viewed in the GUI. (Why is the plot rendering so poor for uploaded workeets on this site?)

I changed the first (of the innermost pair) integral to go from 1 to infinity (instead of 100), as that allowed exact integration after a changed of variables and assumptions that matched the outer integration variables' ranges. Let me know it this is not ok. (The integrand is decaying...)

It was a bit awkward to make some of the integrands be procedures, but I found that I needed to avoid the costly expansion of integrands that evalf/Int attempts. So instead I used the expandoff command to prevent such unwanted expansions. (Without disabling the relevant expansions the computing of the outer integral caused memory exhaustion on my computer.)

I found the final computed plot to be strange over the 0.0 .. 0.1 domain. The are also some wiggles over the 0.1 .. 2.0 domain. The latter I tried to resolve by raising Digits (15, and 30, as attempts), and refining the various epsilon tolerances, and replacement of the NAG methods by _Dexp. But that just made things slower, without the plot being smoother over than subdomain.

Note that repeating the exact integration result, after a full run through the worksheet, needs either the right call to expandon or a restart.


restart:

plots:-setoptions(gridlines=false);

d:=1:
s:=8/10:
c1:=sqrt((s)/Pi/r^3)/2 * (-sin(r*(u-1)^2/4/(s)+Pi/4)+sin(r*(u+1)^2/4/(s))/sqrt(2)):


c22:=-((u+1)/(4*Pi*r*sqrt(y-1)))*(exp(-r*y*(u+1)^2/(8*s)))*(sin(r*y*(u+1)^2/8/(s*(y-1))+Pi/4)/2+sin(r*y*(u-1)^2/8/(s*(y-1))+Pi/4)):
c2:=Int(c22, y= 1..infinity):

value(student[changevar](Y=sqrt(y-1),c2,Y)) assuming r>1, r<100, u>1, u<10:
alt_c2:=simplify(combine(simplify(%)),size) assuming r>1, r<100, u>1, u<10;

-(1/10)*10^(1/2)*(exp(-(5/32)*r*(u+1)^2*(1+2^(1/2)))*sin((5/32)*2^(1/2)*r*(u+1)^2+(5/32)*r*(u+1)^2+(1/4)*Pi)+2*exp((1/32)*(-5*u^2+5)*r*2^(1/2)-(5/32)*r*(u+1)^2)*sin((1/32)*(5*u^2-5)*r*2^(1/2)+(5/32)*r*(u-1)^2+(1/4)*Pi))*(1/(r*Pi))^(1/2)/r


c33:=(sin(r*y*(u+1)^2/8/(s*(y-1))+Pi/4)+sin(r*y*(u-1)^2/8/(s*(y-1))+Pi/4))*(((d*s)/(Pi*(r^2)*y*sqrt(y-1))*exp(-r*y*(u+1)^2/8/s))-((d^2*sqrt((2*s^3)/(Pi*(y-1)*y^3*r^5)))*exp(d*(u+1)+(2*d^2*s)/(y*r))*erfc((r*y*(u+1)+4*d*s)/(2*sqrt(2*s*r*y))))):
c3_1:=Int(c33, y= 1..2);

c3_2:=simplify(Int(c33, y= 2..infinity, epsilon=1e-6, method=_d01amc),size) assuming r>0, u>0, u<10;

Int((sin((5/32)*r*y*(u+1)^2/(y-1)+(1/4)*Pi)+sin((5/32)*r*y*(u-1)^2/(y-1)+(1/4)*Pi))*((4/5)*exp(-(5/32)*r*y*(u+1)^2)/(Pi*r^2*y*(y-1)^(1/2))-(8/25)*10^(1/2)*(1/(Pi*(y-1)*y^3*r^5))^(1/2)*exp(u+1+(8/5)/(y*r))*erfc((1/8)*(r*y*(u+1)+16/5)*10^(1/2)/(y*r)^(1/2))), y = 1 .. 2)

Int((sin((5/32)*r*y*(u+1)^2/(y-1)+(1/4)*Pi)+sin((5/32)*r*y*(u-1)^2/(y-1)+(1/4)*Pi))*((4/5)*exp(-(5/32)*r*y*(u+1)^2)/(Pi*r^2*y*(y-1)^(1/2))-(8/25)*10^(1/2)*(1/(Pi*(y-1)*y^3*r^5))^(1/2)*exp((1/5)*(8+5*r*y*(u+1))/(y*r))*erfc((1/8)*(r*y*(u+1)+16/5)*10^(1/2)/(y*r)^(1/2))), y = 2 .. infinity, epsilon = 0.1e-5, method = _d01amc)

eval(c3_2, [u=1.2, r=3.1]):
evalf(%);

-0.5549288498e-5

alt_c3_1 := simplify(combine(student[changevar](Y=1/(y-1), c3_1, Y)),size) assuming r>0, u>0, u<10:
alt_c3_1 := Int(op(1,alt_c3_1), Y=1..100, epsilon=1e-6, method=_d01akc);

Int(-(8/25)*(sin((5/32)*r*(Y+1)*(u+1)^2+(1/4)*Pi)+sin((5/32)*r*(Y+1)*(u-1)^2+(1/4)*Pi))*(Y^2*exp((1/5)*(5*(u+1)*(Y+1)*r+8*Y)/(r*(Y+1)))*erfc((1/8)*((16/5+(u+1)*r)*Y+(u+1)*r)*10^(1/2)/(((Y+1)*r)^(1/2)*Y^(1/2)))*Pi*10^(1/2)-(5/2)*exp(-(5/32)*r*(Y+1)*(u+1)^2/Y)*Y^(3/2)*((Y+1)*Pi*r)^(1/2))/(r^2*(Pi*Y*r+Pi*r)^(1/2)*Pi*Y^2*(Y+1)), Y = 1 .. 100, epsilon = 0.1e-5, method = _d01akc)

evalf(eval(alt_c3_1, [u=1.2, r=3.1]));

0.1264770573e-2

plot(eval(op(1,alt_c3_1), [u=1.2, r=3.1]), Y=1..100, size=[500,200]);

g1:=c1+alt_c2+alt_c3_1+c3_2:

evalf(eval(g1, [u=1.2, r=3.1]));

-0.6951359046e-1

evalf(eval(g1, [u=1.2, r=10.6]));

-0.7456884432e-2

CodeTools:-Usage( plot( eval(g1, [u=1.2]), r=1..100, adaptive=false, numpoints=300, size=[500,200] ) );

memory used=52.17MiB, alloc change=8.00MiB, cpu time=2.54s, real time=2.71s, gc time=0ns

expand(expandoff());
expandoff(sin, cos, exp, erf, erfc);

expandoff()

#g2_pre := Int(unapply(eval(g1, [u=1.2]), r), 1..100, epsilon=1e-5, method=_Dexp):
#evalf(g2_pre);

g2_pre := Int(g1, r=1..100, epsilon=1e-3, method=_Dexp):
CodeTools:-Usage( evalf(eval(g2_pre, [u=4.1])) );

memory used=189.97MiB, alloc change=32.00MiB, cpu time=11.44s, real time=11.19s, gc time=624.00ms

0.6729803756e-1

g2:= unapply(g2_pre,u):

evalf(g2(2.6));

-.1477074698

CodeTools:-Usage( evalf(g2(4.0)) );

memory used=190.19MiB, alloc change=0 bytes, cpu time=12.56s, real time=12.22s, gc time=733.20ms

0.8051797299e-1

CodeTools:-Usage( plot(g2, 0.1..10, adaptive=false, numpoints=100) );

memory used=43.22GiB, alloc change=384.00MiB, cpu time=60.07m, real time=58.65m, gc time=3.32m

CodeTools:-Usage( plot(g2, 0.1..2.0, adaptive=false, numpoints=50) );

memory used=2.44GiB, alloc change=0 bytes, cpu time=2.49m, real time=2.41m, gc time=9.13s

 

 


Download tripplint_expandoffD.mw

acer

Previous answers are fine, though this particular plotting example can also be handled by rescaling the expression. And below is another way to avoid "hardware floats".


restart:

ee:=.1126460951*t-0.7049523744e-1-1.090463096*10^1390*exp(-1.597924898*t);

.1126460951*t-0.7049523744e-1-0.1090463096e1391*exp(-1.597924898*t)

# Use software floats by setting Digits>evalhf(Digits)=15 ,
# since UseHardwareFloats=deduced by default.

Digits:=round(evalhf(Digits))+1:
P1 := plot(ee, t=2000..2001, numpoints=30,
           color=blue, style=point, symbol=cross, symbolsize=20):
Digits := 10:

# Use software floats by setting the value of UseHardwareFloats.

UseHardwareFloats:=false:
P2 := plot(ee, t=2000..2001, numpoints=20, color=green, style=point):
UseHardwareFloats:=deduced:

# Rescale the expression.

ff := expand(eval(ee, t=2000+tbar));
P3 := plottools:-transform((x,y)->[x+2000,y])(plot(ff, tbar=0..1, color=red)):

225.2216950+.1126460951*tbar-125.2216950*exp(-1.597924898*tbar)

plots:-display( P1, P2, P3, gridlines=false );

 

 


Download sfloats.mw

acer

This is what I have so far...

It produces a much simpler form of the result than what you previously obtained from int, and it demonstrates that this is equal to your expected form (involving coth).

It also shows how your short form involving coth can be turned into this result (much simpler than previously obtained) programatically.

But so far I haven't found a way to turn this new (simpler) form of the result into your equivalent form involving coth.

 

restart:

ee := C1 + C2*(C3/(T*sinh(C3/T)))^2 + C4*(C5/(T*cosh(C5/T)))^2;

C1+C2*C3^2/(T^2*sinh(C3/T)^2)+C4*C5^2/(T^2*cosh(C5/T)^2)

desired := C1*(Tsys-Tref) + C2*C3*(coth(C3/Tsys)
           - coth(C3/Tref)) - C4*C5*(tanh(C5/Tsys)-tanh(C5/Tref));

C1*(Tsys-Tref)+C2*C3*(coth(C3/Tsys)-coth(C3/Tref))-C4*C5*(tanh(C5/Tsys)-tanh(C5/Tref))

# By mapping int over ee (which is a sum of terms) we can obtain a terser answer.
# That's nice, but ideally we'd like to obtain `desired` above (programmatically).

raw := map(int,ee, T=Tref..Tsys)
       assuming Tref > 0, Tsys > Tref, C3 > 0, C5 > 0;

C1*(Tsys-Tref)-2*C2*C3*(exp(2*C3/Tsys)-exp(2*C3/Tref))/((exp(2*C3/Tref)-1)*(exp(2*C3/Tsys)-1))-2*C4*C5*(exp(2*C5/Tsys)-exp(2*C5/Tref))/((exp(2*C5/Tref)+1)*(exp(2*C5/Tsys)+1))

# The difference produces 0, after conversion to exp form.
# It's awkward to need simplify(..,size) followed by plain simplify. But, OK.

simplify(simplify(convert(raw - desired, exp),size));

0

# Let's consider the 2nd term of `ee`, and see whether we can convert
# that into the 2nd term of `desired`. If we can it might give a hint
# as to how to go the other way...

raw1 := int(C2*(C3/(T*sinh(C3/T)))^2, T=Tref..Tsys)
        assuming Tref > 0, Tsys > Tref, C3 > 0, C5 > 0;

-2*C2*C3*(exp(2*C3/Tsys)-exp(2*C3/Tref))/((exp(2*C3/Tref)-1)*(exp(2*C3/Tsys)-1))

des1 := convert(C2*C3*(coth(C3/Tsys) - coth(C3/Tref)),exp);

C2*C3*((exp(C3/Tsys)+exp(-C3/Tsys))/(exp(C3/Tsys)-exp(-C3/Tsys))-(exp(C3/Tref)+exp(-C3/Tref))/(exp(C3/Tref)-exp(-C3/Tref)))

# The corresponding pieces simplify to zero, after conversion to exp form. Good.

simplify(raw1 - des1);

0

# Note that we can successfully convert `des1` back to the
# middle term of `desired`. Good.
convert(des1,trigh):
convert(%,coth):
simplify(%,size);

-C2*C3*(coth(C3/Tref)-coth(C3/Tsys))

# This converts `des1` to `raw1`. OK.
# Hopefully this will inspire me for a way to go the other way...

simplify(expand(numer(des1)*exp(C3/Tsys)*exp(C3/Tref)))
  /simplify(factor(expand(denom(des1)*exp(C3/Tsys)*exp(C3/Tref))));

normal(% - raw1);

-2*C2*C3*(exp(2*C3/Tsys)-exp(2*C3/Tref))/((exp(2*C3/Tref)-1)*(exp(2*C3/Tsys)-1))

0

 

 

Download trighint1.mw

acer

restart;

X:=Vector([seq(-evalhf(2*Pi)..evalhf(2*Pi),.1)],datatype=float[8]):

Y:=map(sin,X):

F:=proc(x, {degree::posint:=3})
    if not type(x,numeric) then return 'procname'(args); end if;
    CurveFitting:-ArrayInterpolation(X, Y, x,
                     ':-method'=':-spline', ':-degree'=degree):
end proc:

evalf(Int(F, 0..Pi));
                   1.9999997215809067

evalf(Int(x->F(x,degree=3), 0..Pi));
                   1.9999997215809067

evalf(Int(x->F(x,degree=5), 0..Pi));
                   1.999999999903325

acer

With a slightly stronger hint for the restriction on parameter s2 the Optimization:-LSSolve command can also be used here.


restart:

X := convert(ExcelTools:-Import(cat(kernelopts(homedir),"/Downloads/data.xlsx"),
                                "Blad1", "A2:A150"),
             Vector):

Y := convert(ExcelTools:-Import(cat(kernelopts(homedir),"/Downloads/data.xlsx"),
                                "Blad1", "B2:B150"),
             Vector)/~100:

# If ignoring the uppermost (mostly flat) Y data.
#X := X[1..130]: Y:=Y[1..130]:

N := LinearAlgebra:-Dimension(X):

Model := 0.5*a*erfc(0.5*2^0.5*((-x+m1)/s1)) + (0.5-0.5*a)*erfc(0.5*2^0.5*((-x+m2)/s2)):

# weighting by 1/y^2 , which places more value on being close when y is small.
#QQ := seq(eval((Model-y)/(abs(y)^(1/4)),[x=X[i],y=Y[i]]), i=1..N):

# no weighting
QQ := seq(eval(Model-y,[x=X[i],y=Y[i]]), i=1..N):

# A closer hint is required here, for the lower bound on s2.
# And that is quite picky. It's not as robust as DirectSearch.
#
# It may be that s2>=2 fails while s2>=3 succeeds, depending on weighting
# and the number of data points.

OSol := Optimization:-LSSolve([QQ],
                              [a>=0, a<=1, m1>=0, s1>=0, m2>=0, s2>=2, m1<=60, m2<=60],
                              output=solutionmodule):

OSol:-Results("solutionpoint");

[a = HFloat(0.5148169333140216), m1 = HFloat(22.890288919515136), m2 = HFloat(9.516048986257628), s1 = HFloat(6.301805243957222), s2 = HFloat(3.3676295294923713)]

OFittedModel := eval(Model, OSol:-Results("solutionpoint"));

HFloat(0.2574084666570108)*erfc(-HFloat(0.11220701904078074)*x+HFloat(2.5684510846410076))+HFloat(0.24259153334298922)*erfc(-HFloat(0.20997166547194032)*x+HFloat(1.9981006543570836))

plot([OFittedModel, diff(OFittedModel,x), <X|Y>], x=min(X)..max(X),
     style=[line$2,point], color=[red$2,blue], gridlines=false);

 

NULL

NULL


Download data_fit_B.mw

acer

You didn't upload your data file (you can just zip it, and fake the extension, btw...) so I have to guess as to how you made and saved it.

But here is the result of a little experiment, using 64bit Maple 17 for Windows 7.

restart;

# Import it, with all entries imported as strings.
#
M := ImportMatrix(cat(kernelopts(homedir),"/My Documents/mapleprimes/md1.csv"),
                  delimiter=",",datatype=string);

                      ["Symbol"  "2015-08-15"  "2016-08-15"]
                      [                                    ]
                 M := [ "TFSC"      "9.76"        "9.62"   ]
                      [                                    ]
                      [ "PIH"       "7.63"        "7.57"   ]

# Strip off the restrictive string datatype.
#
M := Matrix(M, datatype=anything):

# Parse everything but the first column and row, to get numbers.
#
M[2..,2..]:=map(parse,M[2..,2..]):

M;

                   ["Symbol"  "2015-08-15"  "2016-08-15"]
                   [                                    ]
                   [ "TFSC"       9.76          9.62    ]
                   [                                    ]
                   [ "PIH"        7.63          7.57    ]

 

The file md1.zip contains the .csv file I used.

md1.zip

md1.mw

[edit] Now that the OP has uploaded a zipped .csv file, I checked and the above works the same on that data1.csv file.

acer

@jaypantone Do you see the same buffered/delayed effect for userinfo statements? (Those have the nice feature that you can turn them all on or off with a single command, and also control different levels of detail. They ought to display in a visually similar way in CLI and Std GUI)

Eg,

p := proc()
  userinfo( 1, p, `This is a userinfo statement`);
  userinfo( 3, p, `This is a level 3 a userinfo statement`);
  userinfo( 1, p, nprintf("This is a level %a userinfo statement,\nconstructed with nprintf", 1));
end proc:

p();

infolevel[p]:=3:
p();

infolevel[p]:=1:
p();

It's interesting that you don't see the delay problem with the `print` command. Here's a thought: does using `print` or `lprint` to print a single character string such as " ", interleaved with your delay-buffered `printf` statements, help at all?

Is this the kind of thing you want?

restart:

x:=[1992,1994,1996,1998,2000,2002,2004]:
y:=[325,310,266,217,178,159,161]:

Statistics[ColumnGraph](y,captions=[seq(sprintf("%a\n\n",_n),_n=x)]);

kernelopts(version);

          Maple 12.02, X86 64 WINDOWS, Dec 10 2008 Build ID 377066

acer

f := 5*A^4*B^3*C^7   +   3*A^2*B^1*C^7  +  31*A^3*B^6*C^11;

                          3  6  11      4  3  7      2    7
                 f := 31 A  B  C   + 5 A  B  C  + 3 A  B C 

Exponents := proc(p,x)
  local F;
  if p::`+` then
    [seq(degree(F,x), F in p)];
  else
    [degree(p,x)];
  end if;
end proc:

Exponents(f, A);
                                  [3, 4, 2]

Exponents(f, B);
                                  [6, 3, 1]

Exponents(f, C);
                                 [11, 7, 7]

Exponents(31*A^3*B^6*C^11, C);
                                    [11]

acer

If you want to call the LinearAlgebra package's commands with their short form names then at the start of your procedures include the statement,

uses LinearAlgebra;

For example,

f := proc(A)
  local res;
  uses LinearAlgebra;
  res := Basis(A);
end proc:

f( [<0,1,1>,<1,2,1>,<1,1,0>] );

                                 [[0]  [1]]
                                 [[ ]  [ ]]
                                 [[1], [2]]
                                 [[ ]  [ ]]
                                 [[1]  [1]]

If you are writing a module based package then you can do that within each of its procedures, be they exports or local (to the module) procedures.

Basically the `uses` statement sets up the relevant name bindings within your procedure, somewhat analogously to how `with` works at the top-level. (nb. `with` is not the thing to do, inside a procedure.)

The `uses` facility is documented in the Description section of the help-page for proc (procedure).

acer

restart:

limit((b^(d+1)-1)/((b-1)*b^d), d = infinity) assuming b>1;

                                      b  
                                    -----
                                    b - 1

limit((b^(d+1)-1)/((b-1)*b^d), d = infinity) assuming b<-1;  # hmm

                                  undefined

Q := simplify( (b^(d+1)-1)/((b-1)*b^d) ) assuming b<>1;

                                         (-d)
                                    b - b    
                               Q := ---------
                                      b - 1  

R := limit(Q, d = infinity) assuming b<-1 or b>1;

                                        b  
                                 R := -----
                                      b - 1

limit(Q, d = infinity) assuming b>=0 and b<1;

                                  infinity

limit(Q, d = infinity) assuming b>=-1 and b<0;

                                  undefined

What is going on as b->1 and d->infinity?

acer

Do you mean something like this? I am guessing that you want subscripts rather than underscores, which in your Maple 2015 can be done using a literal double-underscore.

plot( [[0,0]], labels=[Omega/omega__n,a__0(m)] );

If you want that m to be upright and not italic, you could do it as say,

labels=[typeset('Omega/omega__n'), typeset('a__0(`#mn("m")`)')]

acer

Is this the kind of thing you mean?

restart:

N := 50:

e2 := [seq(k*Pi/N, k=-N..N)]:
e3 := evalf(map(sin, e2)):

e4 := CurveFitting:-Spline(e2, e3, x):

PD := proc(p, v)
  local L;
  L:=convert(p, list);
  piecewise(seq([L[2*i-1],diff(L[2*i],v)][], i=1..floor(nops(L)/2)),
                diff(L[-1],v));
end proc:

de4 := PD(e4, x):

plot([e4, de4], x=-Pi..Pi);

 

acer

There is a call in the OpenMaple API for querying the interrupt signal. A lot of dsolve/numeric is in external compiled code, which could make use of that.

acer

First 221 222 223 224 225 226 227 Last Page 223 of 336