2448 Reputation

14 years, 26 days

by applyrule...

Yes, a simple rule is useful for completing acer's simplification and thus finding all the solutions:

```trig_sumtoprod:=[
sin(a::algebraic)+sin(b::algebraic)=2*sin((a+b)/2)*cos((a-b)/2), sin(a::algebraic)-sin(b::algebraic)=2*cos((a+b)/2)*sin((a-b)/2), cos(a::algebraic)+cos(b::algebraic)=2*cos((a+b)/2)*cos((a-b)/2), cos(a::algebraic)-cos(b::algebraic)=2*sin((a+b)/2)*sin((b-a)/2)
]:

gg:=applyrule(trig_sumtoprod,ff);
2
2           x
gg := -2 sin(1/2 x  + x) sin(----)
2

solve(gg,{x},allsolutions);
1/2          1/2          1/2          1/2
{x = 2    (Pi _Z1~)   }, {x = -2    (Pi _Z1~)   },
1/2                            1/2
{x = -1 + (1 + 2 Pi _Z2~)   }, {x = -1 - (1 + 2 Pi _Z2~)   }
```

And certainly, it would be better if four different "_Zposint" names were used in the output here as these solution labels are independent from each other.

In my opinion, it is not an intrinsic problem of cartesian coordinates but of using a fixed rectangular mesh. The usage of an adaptive mesh, even in cartesian coordinates, should improve the quality of the plot drastically. This is the point that Worfram Research is making about this plot in its recent comparison.

But Maple does much better in implicitplot3d, precisely adapting the grid, as you can see :

```with(plots):
implicitplot3d(x^2+y^2+z^2=25,x=-6..6,y=-6..6,z=0..6,axes=boxed);
```

So, if it is being done for implicitplot3d, why it is not done for plot3d?

abbreviation of derivatives...

For short input of derivatives (and long output), diff_table may become handy:

```with(PDEtools, diff_table):
U := diff_table(u(x)):
U[x];
d
-- u(x)
dx
U[]*U[x,x];
/ 2      \
|d       |
u(x) |--- u(x)|
|  2     |
\dx      /
```

See ?PDEtools,diff_table. On the other hand declare, already mentioned by acer, is for short output (and long input) of those derivatives. You may also find useful looking at ?PDEtools,ToJet and family.

assuming real or positive...

For this purpose, assuming is most convenient, see ?assuming,details for examples of ... assuming real or ... assuming positive constructs. Be aware though that some commands have not been adapted yet to the usage of this syntax.

Impossible...

The situation of the Classic GUI, and GUIs in general, has been the subject of several recent threads like:

Classic worksheet and 64bits

Problem viewing old Maple Classic worksheets in Maple Standard

Old maple software on a new computer error

How do I flush out the data memory build up?

As you can see, Classic seems condemned to its "extinction", possibly in a short time. And no replacement will be provided.

Not so easy...

The issue of the "constant" of integration being not so constant, and its influence on definite integration via FTOC was discussed several times like in these threads:

A Perilous Tale of Definite Integration

Discontinuous antiderivatives

Funny behavior with int

On the other hand, Maple uses the principal branch approach to logarithm (see ?ln ), rather than a Riemann surface multibranch approach. Yet, there is a conection between the branch index and the unwinding number (see ?unwindK ), as explained in this paper:

R.M. Corless, D.J. Jeffrey, Editors' corner: The unwinding number. SIGSAM Bulletin 116 (1996). PDF version

sorting and symmetry...

Certainly, debugging shows that both sorting by a set and symmetry play a role in this bug. Sorting occurs when trying to match a sum as in (1/3)*Zeta^5+(1/2)*Zeta^2, and takes place in PatternMatching:-AlgStruct:-commutator:

```kernelopts(opaquemodules=false):
showstat(PatternMatching:-AlgStruct:-commutator,3);
PatternMatching:-AlgStruct:-commutator := proc(expr, pattern, operation)
local bindings, patset, pat, literals, found, lit, t, u, k;
...
3   literals := {op}(expr);
...
end proc
```

So that the term with exponent 2 gets the first position, even if it was second in the input and output:

```expr:=(1/3)*Zeta^5+(1/2)*Zeta^2;
5           2
expr := 1/3 Zeta  + 1/2 Zeta

{op}(expr);
2      5
Zeta   Zeta
{-----, -----}
2      3
```

Then it is sent first for trying a match. And because of the symmetry of the expression, it is taken as the relevant binding, which fails when checked later against the condition:

```infolevel[patmatch]:=3:
trace(PatternMatching:-AlgStruct:-matchRec):
patmatch((1/3)*Zeta^5+(1/2)*Zeta^2, conditional(Zeta^n::posint*y::anything+z::anything,
n >= 3), 's');s;s:='s':
...
matchRec:
matching expression: 1/3*Zeta^5+1/2*Zeta^2
...
matchRec:
matching expression: 1/2
...
matchRec:
matching expression: Zeta^2
...
{--> enter matchRec, args = 1/3*Zeta^5+1/2*Zeta^2, [conditional(`/PATTERN`(
`patmatch/N`),3 <= n)], n = 2, y = 1/2, z = 1/3*Zeta^5
5
Zeta
bindings := n = 2, y = 1/2, z = -----
3
matchRec:
matching expression: 1/3*Zeta^5+1/2*Zeta^2
against pattern: [conditional(`/PATTERN`(`patmatch/N`),3 <= n)]
p := conditional(/PATTERN(patmatch/N), 3 <= n)
<-- exit matchRec (now in matchCommOp) = FAIL}
bindings := FAIL
FAIL
...

```

So, workarounds involve breaking the symmetry as here:

```patmatch(1/2*ZZeta^2+(1/3)*Zeta^5, conditional(Zeta^n::posint*y::anything+z::anything,
n >= 3), 's'); s;s:='s':
true
2
ZZeta
[n = 5, y = 1/3, z = ------]
2
```

Why changes affect matching...

Frequently, such changes affect matching because a bug is hit. Indeed, the PatternMatching package is quite buggy and few bugs were fixed since its facilities were introduced in Maple V Release 5, some 15 years ago. Consider some variations of your example:

```patmatch((1/2)*Zeta^2+(1/3)*Zeta^5, conditional(Zeta^n::posint*y::anything+z::anything, n >= 3), 's');s;s:='s':
false
s

patmatch((1/2)*Zeta^2+(1/3)*Zeta^5, conditional(Zeta^n::posint*y::anything+z::anything,
n< 3), 's');s;s:='s':
true
5
Zeta
[n = 2, y = 1/2, z = -----]
3

patmatch((1/2)*Zeta^2+(1/3)*Zeta^5, Zeta^n::posint*y::anything+z::anything, 's');s;s:='s':
true
5
Zeta
[n = 2, y = 1/2, z = -----]
3

```

It sounds like n is bound to 2 before reaching the evaluation of the condition.

Your second question is most interesting. I also request a better pattern matching facility.

why it doesn't work...

By using the "property" linear a procedure is assigned to phi such that for an argument of type `*`, like x*sigma, it looks for "the constant", cf say, in this product, meaning an object of type constant. If it finds it (<>1) it returns cf*phi(term). But as neither x nor sigma are type constant, it returms phi(x*sigma) by line 11 in the code for phi below:

```> define('phi','linear',phi(x::name*sigma)=phi(x)*sigma);
> showstat(phi);
phi := proc()
local theArgs, arg, look, me, cf, term;
1   me := eval(procname,1);
2   theArgs := args;
3   arg := args[1];
4   if arg = 1 then
5     NULL
elif type(arg,'name') then
6     NULL
elif type(arg,'constant') then
7     return arg*procname(1,args[2 .. -1])
elif type(arg,'`+`') then
8     return map(procname,args)
elif type(arg,'`*`') then
9     cf, term := selectremove(type,arg,'constant');
10     if cf = 1 then
11       return ('procname')(args)
else
12       return cf*procname(term,args[2 .. -1])
end if
end if;
13   look := tablelook(('procname')(theArgs),'[`/POS`(1,phi,1), `/KOMUTA`(`/POS`(1,1,`*`),`/ODER`([`/LITER`(1,sigma), `/BIND`(1,`/x1`::name)])), `/PATTERN`(`/FUNCNAME`(`/x1`)*sigma)]');
14   if look <> FAIL then
15     eval(look,`/FUNCNAME` = procname)
else
16     ('procname')(theArgs)
end if
end proc
```

Certainly, this design is a bit rudimentary. A workaround is "declaring" x as a constant ( see ?constant ):

```constants:=constants,x;
constants := false, gamma, infinity, true, Catalan, FAIL, Pi, x
type(x,constant);                                      truephi(x*sigma);
x phi(sigma)
```

Note that I have quoted the term "property", as used in ?define , because this term is used with a different meaning and syntax elsewhere in the system (see ?property ). Also, "declaring" the type of an object, like constant here, is an unusual construct in Maple.

missing factor...

It does not suffice because of the factor 1/2 in the expression. It works by adding a corresponding factor in the pattern, like:

```patmatch((1/2)*Zeta^3, conditional(a::fraction*Zeta^n::posint, n >= 3), 's');s;
true
[a = 1/2, n = 3]
```

better methods...

For this kind of matching PDEtools:-Solve is, probably, the best method:

```PDEtools:-Solve(f,[a,b],independentof=x);
{a = 2, b = 5}
```

It can be done also with patmatch this way:

```patmatch(2*exp(x) + 5*exp(2*x),a::numeric*exp(x)+b::numeric*exp(2*x),'p');p;
true
[a = 2, b = 5]
```

It involves a bit more complex input as it allows for more sophisticated matching.

Also, it can be done with typematch, which is computationally more efficient, but the required input is quite too long and hackish, hence much less user-efficient:

```typematch(2*exp(x) + 5*exp(2*x),`&+`(`&*`(a::numeric,exp(identical(x))),
`&*`(b::numeric,exp(`&*`(2,identical(x))))),'t');t;
true
[a = 2, b = 5]
```

In my opinion, the frontend way is also too hackish for the ordinary user.

Archive vs source...

Indeed, an alternative to saving code to an archive file is keep using text (structured) source files by means of read statements and \$include preprocessor directives. Some advantages of the source way are simpler code development (any change involves just edit and save the relevant text files), and better documentation of this code (comments are kept available). Pro and cons of either approach were discussed in this thread. Further details about structured source files are available in the Programming Guide, Chapter 11, Sections 11.4 and 11.5.

Finally, Alexandra, in her recent MPE advertisement post argued that the structured source file approach is "old technology", but I do not see a proof for this statement.

MultiSeries...

I think that a better answer is provided by MultiSeries:-limit:

```MultiSeries:-limit( a(n), n=infinity );
undefined

MultiSeries:-limit( b(n), n=infinity );
undefined

MultiSeries:-limit( c(n), n=infinity );
undefined

```

I do not observe a significant improvement of the package RealDomain in the recent versions of Maple.

root finding...

The error messages contain the name lambda[i], instead of the numeric values previously assigned to lambda[1] and lambda[2]. It suggests a 2-D input problem. For this case, where A is a sum of two terms, It seems to me easier and simpler to use an explicit form, by replacing Sum by add, and substituting the numeric values only then. Then solve has no problem in finding the three roots of (the numerator of) z-A(z):

```A := Sum(lambda[i]*sigma[i]/(lambda[i]+mu-mu*z), i = 1 .. 2):
s:=lambda[1]= 18, lambda[2] = 16, sigma[1] = .149883,
sigma[2] = .850117, mu = 27, eta = 12, xi = 8: