acer

32333 Reputation

29 Badges

19 years, 326 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

Here's one way to manipulate the equation in question.

Download File_to_help_a.mw

It worked for me, using Maple 2015.2., after I got changed the double .xlsx.xlsx filename extension of your attachment to just .xlsx .

Let me repeat my first question from above, which you did yet not answer. Does it work when you reference the file explicitly, like say the following?

ExcelTools:-Import("C:/Users/Usman/Desktop/Employees.xlsx", 1,"A1:B101");

By the way, Maple 2015 is not the same as Maple 15. If you're going to mark your Questions with the version you're using then please keep that in mind, thanks.

I changed your last two lines to assign to A and B rather than a and b, since you were already using a[0],a[1], etc, and the collision of names seems unnecessary and not useful.

I suggest simplifying "coefficients" in A after collecting. But I'd agree than collecting (first) wrt y[n] is likely best.

Also, simplifying before applying allvalues seems to save time (and produce a better result perhaps). (The application of allvalues just resolves an inplicit RootOf of a quadratic. I did not look at calling solve with option explicit as possible alternative.)

[edited] I found some simpler forms from my earlier answer. Here's the earlier answer, but now with an example call to radnormal and simplify(..,size) which reduces the size about 8 times smaller than I had before.
 

restart:
P:=a[0]+(a[1]*x)/(1+(a[2]*x)/(1+(a[3]*x))):
Q:=diff(P,x):
T:=diff(P,x,x):
e1:=simplify(eval(P, x=q))=y[n]:
e2:=simplify(eval(Q,x=q))=f[n]:
e3:=simplify(eval(Q,x=q+h))=f[n+1]:
e4:=simplify(eval(T,x=q+h))=g[n+1]:
var:=seq(a[i], i=0..3):
M:=e||(1..4):
Cc:=eval(<var>, solve(eval({M}),{var}) ):
for i from 1 to 4 do
        a[i-1]:=Cc[i]:
end do:

Cf:=P:

# your original
A:=y[n+1]=collect(simplify(eval(Cf, x=q+h)),
                  [y[n],f[n],f[n+1],g[n+1]], recursive):

# your original
B:=map(eval@allvalues, [A]):

length(A),length(B);

110982, 400221

newA:=y[n+1]=collect(expand(eval(Cf, x=q+h)),[y[n]],
                     u->simplify(simplify(u),size)):
length(newA);

12320

newB:=[allvalues(newA)]:
length(newB); nops(newB);

33793

2

newerB:=map(ee->collect(expand(ee),[y[n]],
                        u->simplify(simplify(u),size)),newB):
length(newerB); nops(newerB);

19063

2

newestB:=simplify(radnormal(newerB),size): length(%);

2501

newestB[1]; length(%);

y[n+1] = ((h^2*g[n+1]+4*h*f[n+1]+4*y[n])*(h^2*f[n]*g[n+1]^2+4*h*f[n]*f[n+1]*g[n+1]+4*f[n]*f[n+1]^2-4*f[n+1]^3)*q^2+2*h^2*f[n]*g[n+1]*(h*g[n+1]+3*f[n+1])*(h^2*g[n+1]+4*h*f[n+1]+4*y[n])*q+8*h^4*f[n]*f[n+1]^2*g[n+1]+6*f[n]*(h^2*g[n+1]+(4/3)*y[n])*g[n+1]*h^3*f[n+1]+h^6*f[n]*g[n+1]^3+4*h^4*f[n]*g[n+1]^2*y[n]-(g[n+1]*(h^2*f[n]*(q+h)^2*g[n+1]^2+2*h*f[n]*f[n+1]*(h+2*q)*(q+h)*g[n+1]+4*q^2*f[n+1]^2*(f[n]-f[n+1]))^2*(h*g[n+1]-8*f[n]+8*f[n+1])*h^3)^(1/2))/((4*h^2*f[n]*g[n+1]^2+16*h*f[n]*f[n+1]*g[n+1]+16*f[n]*f[n+1]^2-16*f[n+1]^3)*q^2+8*h^2*f[n]*g[n+1]*(h*g[n+1]+3*f[n+1])*q+4*h^3*f[n]*g[n+1]*(h*g[n+1]+2*f[n+1]))

1248

newestB[2]; length(%);

y[n+1] = ((h^2*g[n+1]+4*h*f[n+1]+4*y[n])*(h^2*f[n]*g[n+1]^2+4*h*f[n]*f[n+1]*g[n+1]+4*f[n]*f[n+1]^2-4*f[n+1]^3)*q^2+2*h^2*f[n]*g[n+1]*(h*g[n+1]+3*f[n+1])*(h^2*g[n+1]+4*h*f[n+1]+4*y[n])*q+8*h^4*f[n]*f[n+1]^2*g[n+1]+6*f[n]*(h^2*g[n+1]+(4/3)*y[n])*g[n+1]*h^3*f[n+1]+h^6*f[n]*g[n+1]^3+4*h^4*f[n]*g[n+1]^2*y[n]+(g[n+1]*(h^2*f[n]*(q+h)^2*g[n+1]^2+2*h*f[n]*f[n+1]*(h+2*q)*(q+h)*g[n+1]+4*q^2*f[n+1]^2*(f[n]-f[n+1]))^2*(h*g[n+1]-8*f[n]+8*f[n+1])*h^3)^(1/2))/((4*h^2*f[n]*g[n+1]^2+16*h*f[n]*f[n+1]*g[n+1]+16*f[n]*f[n+1]^2-16*f[n+1]^3)*q^2+8*h^2*f[n]*g[n+1]*(h*g[n+1]+3*f[n+1])*q+4*h^3*f[n]*g[n+1]*(h*g[n+1]+2*f[n+1]))

1248

 

Download simplif_ex3.mw

And here below are two other approaches.

The first of these next approaches is somewhat similar to what I did above.

The second of these next approaches eliminates only a[1],a[2],a[3] as a first step (as opposed to calling solve for all four variables), and then eliminates a[0] from the restrictions that ensue from the first step. That elimination of a[0] produces the pair of results (that previously came from calling allvalues on the quadratic RootOf). This approach gets a pair of formulas each of length 625, which is half the size of the other approaches results.

So now there are three pairs formulas for y[n+1]. Evaluation at random float values shows agreement (but in one of the pairs the agreement can flip partners).
simpl_alt1.mw

The smallest I see so far (using either length or LeafCount as the metric), is,

collect(EXPR,[Gr,Br],u->simplify(simplify(u),size));

where EXPR is the original (as converted to 1D by Preben). That result has length 2645 , without any assumptions, using Maple 2017.3.

simp_expr.mw

restart:

kernelopts(version);

`Maple 2016.2, X86 64 LINUX, Jan 13 2017, Build ID 1194701`

#k=2:
omega:=u/h:
psi:=v/h:
t:=(sum(a[j]*x^j,j=0..2)+a[3]*sin(omega*x)+a[4]*cos(omega*x)+a[5]*sin(psi*x)+a[6]*cos(psi*x)):
F:=diff(t,x):
G:=diff(t,x,x):
p1:=simplify(eval(t,x=q+h))=y[n+1]:
p2:=simplify(eval(F,x=q))=f[n]:
p3:=simplify(eval(F,x=q+h))=f[n+1]:
p4:=simplify(eval(F,x=q+2*h))=f[n+2]:
p5:=simplify(eval(G,x=q))=g[n]:
p6:=simplify(eval(G,x=q+h))=g[n+1]:
p7:=simplify(eval(G,x=q+2*h))=g[n+2]:
vars:= seq(a[i],i=0..6):
Cc:=eval(<vars>, solve({p||(1..7)}, {vars})):
for i from 1 to 7 do
        a[i-1]:=Cc[i]:
end do:
Cf:=t:

K:= collect(combine(simplify(eval(Cf,x=q+2*h),size),trig),{y[n+1],f[n],f[n+1],f[n+2],g[n],g[n+1],g[n+2]},factor):


alpha[1]:=simplify(coeff(K,y[n+1])):
beta[0]:=simplify(coeff(K,f[n]),size):
beta[1]:=simplify(coeff(K,f[n+1]),size):
beta[2]:=simplify(coeff(K,f[n+2]),size):
gamma0:=simplify(coeff(K,g[n]),size):
gamma1:=simplify(coeff(K,g[n+1]),size):
gamma2:=simplify(coeff(K,g[n+2]),size):

H := ee -> collect(numer(ee),[sin],u->simplify(simplify(u),size))/collect(denom(ee),[sin],u->simplify(simplify(u),size)):

newgamma2 := (H@expand)(gamma2);
length(newgamma2);
simplify(expand(gamma2-newgamma2));

((-h^2*v*u*((v^2+8*cos(v)-8)*cos(u)+cos(v)*u^2-u^2-v^2-8*cos(v)+8)*sin(v)-2*h^2*((u^2+2*v^2)*cos(v)-3*cos(u)*v^2-u^2+v^2)*u*(cos(v)-1))*sin(u)-2*h^2*v*(cos(u)-1)*(2*cos(u)*u^2-3*cos(v)*u^2+cos(u)*v^2+u^2-v^2)*sin(v)-h^2*(((4*u^2+4*v^2)*cos(v)^2+((v^2-4)*u^2-4*v^2)*cos(v)-3*u^2*v^2)*cos(u)^2+(((v^2-4)*u^2-4*v^2)*cos(v)^2+4*u^2*v^2*cos(v)+(-v^2+4)*u^2+4*v^2)*cos(u)-3*u^2*v^2*cos(v)^2+((-v^2+4)*u^2+4*v^2)*cos(v)+(2*v^2-4)*u^2-4*v^2))/((4*u*v*(u^2+v^2)*(cos(u)-1)*(cos(v)-1)*sin(v)+4*u^3*v^2*(cos(v)-1)*(cos(v)-cos(u)))*sin(u)-4*u^2*v^3*(cos(u)-1)*(cos(v)-cos(u))*sin(v)+8*u^2*v^2*(cos(u)-1)*(cos(v)-1)*(cos(u)*cos(v)-1))

1081

0

all:=[alpha[1],beta[0],beta[1],beta[2],gamma0,gamma1,gamma2]:
all1:=simplify~(expand~([alpha[1],beta[0],beta[1],beta[2],gamma0,gamma1,gamma2]),size):
all2 := (H@expand)~([alpha[1],beta[0],beta[1],beta[2],gamma0,gamma1,gamma2]):

length~(all);
length~(all1);
length~(all2);

[1, 1945, 1765, 2129, 1941, 2039, 2073]

[1, 1381, 1349, 1429, 1377, 1425, 1441]

[1, 941, 993, 1045, 1033, 977, 1081]

normal(expand~(all-all1));
normal(expand~(all-all2));

[0, 0, 0, 0, 0, 0, 0]

[0, 0, 0, 0, 0, 0, 0]

 

Download simp_ex.mw

Try it under the assumption that x>0 .

restart;

f:=(x,z)->ln(x^z);

                                      / z\
                     f := (x, z) -> ln\x /

simplify(f(x,2)) assuming x>0;

                            2 ln(x)

Now consider a value for x such as -1/3 . Notice that your expected formula doesn't produce the same result.

ln((-1/3)^2), 2*ln(-1/3);

                  -2 ln(3), -2 ln(3) + 2 I Pi

Your Question was, "Can a Data Table be used as an input in a procedure?"

If I understand the question properly, then my Answer is as follows. The name of the unique Array/rtable/Matrix/Vector associated with a particular DataTable can be the argument to a procedure call, as can the unique string identity of a particular DataTable.

Now on to your bullet points, which seem to be more about having an Array associated with a DataTable be returned from a procedure call:

Issue 3)

When your procedure BiPolyNum returns a copy of the Array ary then it is deliberately breaking any connection with the DataTable associated with ary.

Subsequent changes in the DataTable (made manually) will not be accompanied by any changes in the Array returned by BiPolyNum as copy(ary). And vice versa.

So, if you expect the returned Array and the DataTable to be associated, then don't use copy on the return value.

Issue 2)

This is the same as issue 3), except you're not using a procedure. But your copy(ary) is still not going to be associated with the DataTable. A DataTable is associated with only one rtable (Array, say). A copy of that Array won't be associated with the DataTable.

Issue 1)

I'll check whether I can reproduce the lag. You could submit a bug report. I suggest submitting a bug report in which you've inserted the DataTable by hand, via the Components palette, so that it's clear that the issue has nothing to do with the DocumentTools commands.

 

That's not 1D Math output.

It's 2D Math output where the bodies of the operators are showing prefix form rather than infix form.

It's likely that it's related to your use of Units:-Standard , since the rebound arithmetic operators in that package will return calls to the global operators.

It's not clearly a bug. What you're seeing is the bodies of procedures. It's not clear why they *ought* always to pretty-print exactly the same as do plain output expressions. But we might be able to suggest a change to make it happen...

It would make most sense for you to upload an actual Document, which contained all the inputs. (We'd also be able to tell which mnor and major version you're using. There are have been some related changes since Maple 2016.)

You can programmatically insert a new (invisible, so-called) Task Region right after the currently focused Execution Group or Document Block (paragraph). And you can programmatically construct the contents that will go into it.

And that includes contents like Embedded Components such as Math Containers. See the help page for topic,

    DocumentTools,Components,MathContainer

You can also programmatically replace the contents of a previously inserted Task Region.

But an insertion of a new Task Region can only be done from overt code. It cannot be done from within a Button. It can only be inserted below the current Execution Group or Document Block. It cannot be done to some other execution group elsewhere in the sheet.

Part of your description makes it sound like you want "day of the year" to be the independent data and "amount of chemical" to be the dependent data. That makes sense to me, and it's what I show below.

When you write that you want, "day of the year vs amount of chemical" then there may be a confusion in terminology. Usually one talks of plotting dependent quantity vs independent quanity.

restart;

A:=Array([[10,283.2],[21,293.3],[27,294.4],[103,300.7],[211,302.1]]):
M:=Matrix(A);

chem_formula:=13.0+7.0*sqrt(273+temp);
chem_func:=unapply(chem_formula, temp);

M[1..-1,1]; # the day numbers (in the year)

M[1..-1,2]; # the temperatures

map(chem_func, M[1..-1,2]); # the chemical amounts

plot( <M[1..-1,1] | map(chem_func, M[1..-1,2])>,
      view=[1..365, default] );

restart;

eq16 := r(t) = d[vol]*V/(KUS*V^2+L*tau);

r(t) = d[vol]*V/(KUS*V^2+L*tau)

F := (u,v) -> sort(expand(u/v),order=tdeg(v),ascending):

lhs(eq16) = F(numer(rhs(eq16)),V) / F(denom(rhs(eq16)),V);

r(t) = d[vol]/(L*tau/V+KUS*V)

 

Download divid.mw

[edited] This kind of question has been asked several times before -- enough that people have written short re-usable procedures for it. So, you could use A.Jakubi's dividend procedure (and optionally pass it a sorting post-processor similar to what I used above).

restart;

dividend := proc(ex,f:=numer(ex),t:=[expand,expand])
  local n,d;
  n := t[1](numer(ex)/f):
  d := t[2](denom(ex)/f);
  n/d;
end proc:

eq16 := r(t) = d[vol]*V/(KUS*V^2+L*tau);

r(t) = d[vol]*V/(KUS*V^2+L*tau)

dividend(rhs(eq16), V);

d[vol]/(V*KUS+L*tau/V)

dividend(rhs(eq16), V,
         u->sort(expand(u),order=tdeg(V),ascending));

d[vol]/(L*tau/V+KUS*V)

 

Download dividend_ex.mw

You can check that the floats agree under rounding (to less digits), as Kitonum suggested.

Or you can increase the working precision, and then round down to current (default 10) Digits.

Or you can use testfloat to get details, and optionally use testfloat to do a coarser comparison.

restart;

a := (x^2+y^2)^3 = y^2:
b := (x^2+y^2)^(3/2) = y:

listA := evalf(sort([seq(evalf[20](solve({y >= 0, subs(x = i, a)}, {y})), i = 0.5e-1 .. .5, 0.5e-1)])):
listB := evalf(sort([seq(evalf[20](solve({y >= 0, subs(x = i, b)}, {y})), i = 0.5e-1 .. .5, 0.5e-1)])):

evalb( listA = listB );

true

restart;

a := (x^2+y^2)^3 = y^2:
b := (x^2+y^2)^(3/2) = y:

listA := sort([seq(evalf(solve({y >= 0, subs(x = i, a)}, {y})), i = 0.5e-1 .. .5, 0.5e-1)]):
listB := sort([seq(evalf(solve({y >= 0, subs(x = i, b)}, {y})), i = 0.5e-1 .. .5, 0.5e-1)]):

evalb( listA = listB );

false

zip( (a,b)->testfloat( eval(y,a), eval(y,b), 1 ), listA, listB );

[true, true, true, [false, 6., `ulps `], true, true, true, [false, 2., `ulps `], true, [false, 2., `ulps `], true, [false, 3., `ulps `], [false, 2., `ulps `], true, true, [false, 2., `ulps `], [false, 2., `ulps `], [false, 4., `ulps `], true, true]

zip( (a,b)->testfloat( eval(y,a), eval(y,b), 10 ), listA, listB );

[true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]

evalb( `and`( zip( (a,b)->testfloat( eval(y,a), eval(y,b), 1 )=true, listA, listB )[] ) );

false

evalb( `and`( zip( (a,b)->testfloat( eval(y,a), eval(y,b), 10 )=true, listA, listB )[] ) );

true

 

Download float_comparison.mw

In your code to produce the "A" you assign to the name x, like x:=Alist[i][1] . Then you try and construct the "D" while using x as if it were an unassigned name. That won't work. There likely are other issues with the code, which is quite disorganized.

You can keep all your variables organized by using a procedure's local names for dummy variables.

You should be able to produce an unrotated "A" with just three polygons, and without any (white) occluding background, in one line of code. Even better, construct a procedure that returns the plot structure for an "A" (upright, with lower left corner at the origin).

Here's an example. (You could add a color like "gray" to the polygons, of course.) 

restart;

with(plottools):

makeA:=proc()
  uses plots;
  display(
    polygon([[0,0],[1,0],[4,8],[3,8]]),
    polygon([[3,8],[4,8],[7,0],[6,0]]),
    polygon([[2,4],[5,4],[5,3],[2,3]]),
  scaling=constrained);
end proc:

makeA();

P1:=makeA():

plots:-display(rotate(P1, 2*Pi/3));

 

 

plot_letterA.mw

interface( rtablesize = 11 ):  # or higher

w := (x, y) -> piecewise(y <= .5, -2*tanh(y-.25), .5 < y, 2*tanh(.75-y)):

Matrix( 11, 11, (i,j) -> w(i-1,j-1) );

First note that a sequence of items is different from a list of items.

restart;

f := proc()
  print(sprintf( "nargs = %a", nargs ));
  print(sprintf( "args[1] = %a", args[1] ));
  return NULL;
end proc:

f( 1,2,3,4,5 );
                          "nargs = 5"
                         "args[1] = 1"

f( [1,2,3,4,5] );
                          "nargs = 1"
                  "args[1] = [1, 2, 3, 4, 5]"

When f above is passed a sequence of 5 numbers then the number of arguments is 5, and the first argument is just 1. (nargs stands for number of arguments, and args stands for arguments.)

But when f above is passed a list with 5 entries then the number of arguments passed to f is just 1, and the first argument is the whole list.

Your maximum procedure and example call didn't work as intended because you passed it a single list (so nargs is just 1), whereas you've written it to work with a sequence.

Here are some versions that work (several other variations are possible). The first works when passed a sequence of numeric items, and the second works when passed a list of numeric items. I also give a third (which is a minor variation on the second) where the procedure's first parameter L is explicitly declared.

restart;

maximum := proc()
 local r, i;
 r := args[1];
 for i from 2 to nargs do
   if args[i] > r then
     r := args[i];
   end if;
 end do;
 r;
end proc:

maximum( 6,9,4,1 );
                               9

restart;

maximum := proc()
 local r, i, L;
 L := args[1];
 r := L[1];
 for i from 2 to nops(L) do
   if L[i] > r then
     r := L[i];
   end if;
 end do;
 r;
end proc:

maximum( [6,9,4,1] );
                               9

restart;

maximum := proc(L)
 local r, i;
 r := L[1];
 for i from 2 to nops(L) do
   if L[i] > r then
     r := L[i];
   end if;
 end do;
 r;
end proc:

maximum( [6,9,4,1] );
                               9

Secondly, note that the following two lists are NOT similar. One is a list of lists and the other is a list of scalars. The first is a list of 6 lists (each with 2 scalar entries). The second is a list with 12 scalar entries. You cannot operate on them in the exact same manner. BTW, if you changed your trailing colons to semicolons then your output wouldn't be suppressed and you'd be able to more easily see this for yourself.

LC_L:=[[0,0],[0,h],[w,h],[w,w],[b,w],[b,0]];

    LC_L := [[0, 0], [0, h], [w, h], [w, w], [b, w], [b, 0]]

LC_L2:=[(0,0),(0,h),(w,h),(w,w),(b,w),(b,0)];

         LC_L2 := [0, 0, 0, h, w, h, w, w, b, w, b, 0]

Note that round brackets do not produce a structure in any way similar to how square brackets or squiggly brackets do. Square brackets [...] construct a list. Squiggly brackets {...} construct a set. But round brackets serve as delimiters, eg. to mark the scope of arithmetic operations. Round brackets do not construct separate substructures which are subsequently accessible separately using the op command or indexed referencing.

note: round brackets also serve to denote a function call, eg f(x,y), but that's not really relevant to the points made here.

[edited]
A few more subtleties worth knowing: You can index into an expression sequence. But as soon as you pass the expression sequence to a procedure then within that procedure it (normally) gets treated as separate arguments instead of as a unified sequence.

restart;

# A list is stored as a container which could hold an
# expression sequence (amogst other things).
expr := a,b,c,d,e:

expr;
                         a, b, c, d, e

L := [expr]:

L;
                        [a, b, c, d, e]

op(L);
                         a, b, c, d, e

# `op` sees six arguments here, the 3, followed by `a`, and `b`, etc.
op(3, expr);
Error, invalid input: op expects 1 or 2 arguments, but received 6

op(3, L);
                               c

# We can unambiguously index (reference) into the sequence.
expr[2];
                               b

L[2];
                               b

# But once passed to procedure `G`, the sequence is seen as multiple
# arguments, rather than as a single argument.
G := proc(U)
  U[2];
end proc:

# Parameter `U` of `G` takes on the value of the first argument passed.
# Here, that first argument is the list `L`.
G( L );
                               b

# Parameter `U` of `G` takes on the value of the first argument passed.
# Here, that first argument is just `a` and not the whole sequence.
G( expr );
                              a[2]
First 182 183 184 185 186 187 188 Last Page 184 of 336