acer

33275 Reputation

29 Badges

20 years, 260 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@dharr I like this approach, as a heuristic, and often try it.

One idea is that evala, trying to get some kind normal/canonical/standard form, will try to rationalize radicals which are explicit multiplicative factors of the denominator.

So if you have a target form that has, say, a numerator which is just some integer, and a denominator which is a product of radicals, then it seems reasonable that simplifcation of the rationalized reciprocal might be a fruitful approach.

A couple of variants on that theme, which also happen to work here. (The last one is lower strength.)

restart

kernelopts(version)

`Maple 2025.2, X86 64 LINUX, Nov 11 2025, Build ID 1971053`

 

expr := sqrt(x__0+1)*sqrt(-2*beta^2*x__0-2*beta^2+4)*sqrt(-(x__0+1)*(beta^2-1))/((beta^2*x__0+beta^2-2)*(beta^2*x__0+beta^2-x__0-1))

 

`assuming`([1/evala(1/simplify(expr))], [0 < x__0 and x__0 < 1])

2/((-beta^2+1)^(1/2)*(-2*beta^2*x__0-2*beta^2+4)^(1/2))

`assuming`([1/rationalize(1/simplify(expr))], [0 < x__0 and x__0 < 1])

2/((-beta^2+1)^(1/2)*(-2*beta^2*x__0-2*beta^2+4)^(1/2))

NULL

Download Simplify_radical_02_acc.mw

While I often try this as a stage in attacking some problematic example, I find it a little harder to explain, since on the surface it might seem a bit ad hoc to some users.

@C_R If I recall correctly, member nm once showed some experiments with a procedure that would attempt simplification using [at that time, a single call to] a variety of commands such as simplify, evala, combineevalc, etc.

Many years before that I had a more involved utility which did a similar kind of task, but recursively (using multiple command calls), in quite a sophisticated manner. It had various bells&whistles options to allow specification of recursion depth, time-limit, actions to include/exclude, choice of metric to use, extra manipulations like collect, actions-spilt-across-numer/denom, expand, double reciprocation, split action across summads/multiplicads, custom metrics, etc. It would return the command sequence(s) that could attain the most compact form found.

Eg,
     collect( expr, [a, x], u->simplify(factor(u),size) )
or what have you.

It could sometimes reveal very nice results. I called it crush.

There was a sister utility, which could search for optimal trig expression rewrites (recursive combinations of half-angle, double-angle, sum-to-product, product-to-sum, pythagoras, etc) based on trying combinations of selected veiling of trig function instances in the expression. For example, there are expression for which veiling cos(x) (when all others of sin(x), sin(y), cos(y) are still present) can fortuitously lead to a most-compact form.

The first utility was often very useful, since it could often be used not to "out-do" simplify but also to obtain the action chain that would attain the result. The second utility was a more potemtially expensive solution (due to combinatoric selection from trig calls present), for a somewhat more niche topic.

I might have lost both after a couple of hard-drive crashes.

Apart from custom user-defined size metrics, it offered stock choices of MmaTranslator:-Mma:-LeafCount, and `simplify/size/size` (which simplify(...,size) can utilize), etc.

@WD0HHU Yes, susbindets & evalindets are very powerful.

They are made more useful by the scope and power of the type system. It is the second argument to subsindets/evalindets, ie. a type, which specifies which subexpressions to change.

Another tip: sometimes it's helpful to know (or test in advance) which subexpressions would be acted on by subindets. For that one can first call indets instead, giving it only the 1st and 2nd arguments. Ie, their syntax is usefully similar:

    indets( expr, the_type )
subsindets( expr, the_type, the_action )

So it can seem less confusing, to first pin down and figure out what the precise type ought to be, using just indets. Then, you can take just one of the returned subexpressions, and try and figure out when the desired transforming action ought to be. (You may have an action which greatly transforms the subexpressions.)

Figuring it out in these steps can be less confusing that trying to figure everything out at once with subsindets right away. Also, since the result is always an unordered set (rather than a list) it can sometimes be tricky to figure out the whole process that subsindets is doing since you may not know which element of the final set came from which subexpression.

@WD0HHU The direct result of your substitution is an expression that is unsimplified (and unexpanded).

You could apply one of the commands expand, normal, or simplify to that result, to get the explicit zero.

@nm In this case solve returns several solutions (as lists).

And here [solve(...)] is returning a list of lists.

So, here, you'd need to map your stated approach (which itself maps an operator).

And for a list of such lists of lists of equations, you'd need to map yet again at another layer...

I used subsindets because that single call handles all the equations in the whole expression list-of-lists, etc, directly, regardless of nesting depth. Not a map of a map of an action, or what have you.

It's not just that I don't want to have to type out any extra mapping layers. I'm also ok not having to need to think about it (as a single subsindets call suffices here).

@WD0HHU If you run the command,

   [solve(sys,explicit,allsolutions)]

on that system then the various solutions will contain many "trivial" items, such as a=a, or C[1]=C[1], or sigma=sigma, etc.

I find that those are somewhat distracting. So I apply the following to that list of solutions,

   subsindets( that_solution_list,
                       `=`,
                       eq->ifelse(eq,NULL,eq)
                      );

So, what does that do? If replaces with NULL any equation in that raw solve result whose rhs equals its lhs. A trivial equation like  lambda=lambda  has that property, and is one of those removed, ie. replaced by NULL. It's an equation, ie. of type `=`.  And under the evalb test which ifelse applies it returns true.

evalb( lambda=lambda ); # returns true, causing the next line:

ifelse( lambda=lambda, NULL, other ); # returns NULL

For example,

L := [a=b, c=c, d=e, f=f];

       L := [a = b, c = c, d = e, f = f]

subsindets( L, `=`, eq->ifelse(eq,NULL,eq) );

               [a = b, d = e]

So, the trivial identity equations are removed (replaced by NULL), and others are left untouched.

Hope that makes sense.

nb. The various solutions in that list [solve(...)] can be substituted into the original polynomial equations, to show that they really are solutions. But that can also be done with the shortened solutions (with the trivial items removed).

You could submit a Software Change Request (aka bug report) with those details, by filling out the form here.

@Ali Guzel  You didn't supply the details I described as being more important.

I changed your Post into a Question.

But your posting is missing important details. What version are you trying now? More importantly, what did the intermediate results look like in Maple 9.5 or whenever it last worked as desired?

@Hullzie16 For this plotting task it is much faster to use implicitplot rather than a procedure which calls fsolve.

The idea is to first compute the implicit plot where equation R holds (S vs C), and then to transform that plot result, using the T expression as a formula for the new vertical component.

Also, there appear to be two roots, for significant portions of your parameter space.

In this attachment I show Explore working on the implicitplot. I also include the two "curves" generated by taking either the first or second root that fsolve can find, just to show that together they correspond to the implicitplot result.

In the code below the procedures CC (and CC2 and CCboth) are now only used to first show that the new technique is ok. For the faster implicitplot approach (and its Explore) all the calls CC(S,mu,Z,Pr) in expression T are never executed or called(!). Instead, they are replaced by the vertical component y-values from the implicitplot of R, when transforming it. That's what's going on in the second line of procedure Timpl below.

The plot recomputation in the Explore assembly is so much faster with this approach that I can get rid of the continuous option on the Sliders, and get a nice smooth action.

restart;

T := 2^(2/3)*(16*CC(S,mu,Z,Pr)^2*Pi^2 + 2*Pi^2*Z^2 + 16*Pi*S*CC(S,mu,Z,Pr) + 3*S^2)*Pr^(1/3)/(4*(4*CC(S,mu,Z,Pr)*Pi + S)^(2/3)*(2*Pi^2*Z^2 + 4*Pi*S*CC(S,mu,Z,Pr) + S^2)^(2/3)*CC(S,mu,Z,Pr)^(1/3)*Pi^(2/3));

(1/4)*2^(2/3)*(16*CC(S, mu, Z, Pr)^2*Pi^2+2*Pi^2*Z^2+16*Pi*S*CC(S, mu, Z, Pr)+3*S^2)*Pr^(1/3)/((4*CC(S, mu, Z, Pr)*Pi+S)^(2/3)*(2*Pi^2*Z^2+4*Pi*S*CC(S, mu, Z, Pr)+S^2)^(2/3)*CC(S, mu, Z, Pr)^(1/3)*Pi^(2/3))

Tf := unapply(T,S,mu,Z,Pr):

Tf2 := unapply(subs(CC=CC2,T),S,mu,Z,Pr):

R := mu = 2^(2/3)*S*(16*C^2*Pi^2 - 2*Pi^2*Z^2 - S^2)*Pr^(1/3)/(4*(4*C*Pi + S)^(2/3)*(2*Pi^2*Z^2 + 4*C*Pi*S + S^2)^(2/3)*C^(4/3)*Pi^(2/3));

mu = (1/4)*2^(2/3)*S*(16*C^2*Pi^2-2*Pi^2*Z^2-S^2)*Pr^(1/3)/((4*C*Pi+S)^(2/3)*(2*Pi^2*Z^2+4*C*Pi*S+S^2)^(2/3)*C^(4/3)*Pi^(2/3))

Rf := unapply(R,S,mu,Z,Pr):

CCboth:=proc(S,mu,Z,Pr) option remember; local res;
  if not [S,mu,Z,Pr]::list(numeric) then return 'procname'(args); end if;
  res := fsolve(Rf(S,mu,Z,Pr),C=0.01..100,maxsols=2);
  if nops([res])=1 then res,undefined; else res; end if;
end proc:
CC := proc(S,mu,Z,Pr)
  if not [S,mu,Z,Pr]::list(numeric) then return 'procname'(args); end if;
  CCboth(S,mu,Z,Pr)[1];
end proc:
CC2 := proc(S,mu,Z,Pr)
  if not [S,mu,Z,Pr]::list(numeric) then return 'procname'(args); end if;
  CCboth(S,mu,Z,Pr)[2];
end proc:

 

CCboth(1,0,0.5,0.2);
CC(1,0,0.5,0.2);
CC2(1,0,0.5,0.2);

.1938622551, undefined

.1938622551

undefined

CCboth(4,0.5,0.25,0.5);
CC(4,0.5,0.25,0.5);
CC2(4,0.5,0.25,0.5);

.4611869603, 3.243089599

.4611869603

3.243089599

P:=plots:-implicitplot(eval(R,[mu=0.5,Z=0.25,Pr=0.5]),
                       S=0..16,C=0..100,signchange=false);

Timpl := proc(mu,Z,Pr) local P; uses plots, plottools:
  P := implicitplot(eval(R,[:-mu=mu,:-Z=Z,:-Pr=Pr]),
                    S=0..16,C=0..100,signchange=false);

  display(transform((x,y)->[x,eval(eval(T,[CC(:-S,:-mu,:-Z,:-Pr)=y]),
                                   [:-S=x,:-mu=mu,:-Z=Z,:-Pr=Pr])])(P),
          view=[0..15,0..1.5]);

end proc:

 

P1 := Timpl(0.5,0.25,0.5);

# Recall,.. this is not especially fast
P2 := plot(Tf(S,0.5,0.25,0.5),S=0..15,view=[0..15,0..1.5],
           adaptive=false,numpoints=49,color=blue);

# The second if faster than the first, due to remembered values.
P3 := plot(Tf2(S,0.5,0.25,0.5),S=0..15,view=[0..15,0..1.5],
           adaptive=false,numpoints=49,color=magenta);

 

Explore(Timpl(mu,Z,Pr),
        parameters=[[mu=0 .. 1.0, minorticks=0.25],
                    [Z=0..0.5, minorticks=0.1],
                    [Pr=0..1.0, minorticks=0.25]],
        initialvalues=[mu=0.5,Z=0.25,Pr=0.5], adaptview=false);

 

 

Download Explore_Plot_Problem_ac4.mw


Without the above comparison of approaches, this implicitplot approach alone is quite short, and utilizes just your original expression forms for T and R.

T := 2^(2/3)*(16*CC(S,mu,Z,Pr)^2*Pi^2 + 2*Pi^2*Z^2 + 16*Pi*S*CC(S,mu,Z,Pr)
     + 3*S^2)*Pr^(1/3)/(4*(4*CC(S,mu,Z,Pr)*Pi + S)^(2/3)*(2*Pi^2*Z^2
     + 4*Pi*S*CC(S,mu,Z,Pr) + S^2)^(2/3)*CC(S,mu,Z,Pr)^(1/3)*Pi^(2/3)):

R := mu = 2^(2/3)*S*(16*C^2*Pi^2 - 2*Pi^2*Z^2 - S^2)*Pr^(1/3)/(4*(4*C*Pi + S)^(2/3)
          *(2*Pi^2*Z^2 + 4*C*Pi*S + S^2)^(2/3)*C^(4/3)*Pi^(2/3)):

Timpl := proc(mu,Z,Pr) uses plots, plottools:
  display(transform((x,y)->[x,eval(eval(T,[CC(:-S,:-mu,:-Z,:-Pr)=y]),
                                   [:-S=x,:-mu=mu,:-Z=Z,:-Pr=Pr])])(
            implicitplot(eval(R,[:-mu=mu,:-Z=Z,:-Pr=Pr]),
                         :-S=0..16,:-C=0..100,'signchange'=false)),
          'view'=[0..15,0..1.5]);
end proc:

Explore(Timpl(mu,Z,Pr), 'initialvalues'=[mu=0.5,Z=0.25,Pr=0.5], 'adaptview'=false,
        parameters=[[ mu = 0 .. 1.0, 'minorticks'=0.25 ],
                    [ Z = 0..0.5, 'minorticks'=0.1 ],
                    [ Pr = 0..1.0, 'minorticks'=0.25 ]]);

 

 

Download Explore_Plot_Problem_ac4B.mw

@Hullzie16 I prefer assignments over Equation Labels, and I wanted a quick way to shoehorn the R expression into the procedure CC.

There are other ways, eg. using eval(R, [:-S=S,:-mu=mu, etc]) as the argument to fsolve, so that the arguments of CC got put into the R expression when CC were called.  Explore_Plot_Problem_ac2.mw

And here's another variant, using procedures instead of expressions&eval.
Explore_Plot_Problem_ac3.mw

@GFY I wasn't so confused by your use of Eval (vs eval) as I was that you were multiplying D[1] by something. The name D is special, and denotes the differential operator (for use on procs). If your using D[1] as a mere name then I suggest using another name.

On the subject of D, note this comparison of derivates in diff/Diff expression form and in D operator form. Note also that you can utilize Diff instead of diff, versus Eval instead of eval. I'm not saying that D would serve you better, as I don't know your full set of use-cases. But you might find it useful to learn about such, and conversions.

D_diff_ex.mw

(And the D operator can also handle multivariate procs. That's all related to why I found the product involving D[1] confusing. See also the Help-page.)

ps. Like sand15, I simply used lprint of what was actually being sent to algsubs (ie. the result of expand(eqn1)), to see what was going on. And now that's in your tool-set.

I have seen a report of it working in M2025 and M2026 on Windows 11.

@GFY I see now. Somehow I'd got the impression that there might be some other, more involved example.

Yes, this is a key purpose of IntegrationTools:-Expand, which is why I mentioned it in my Answer.

Your example-at-hand shows that I may have been too worried about unwanted extra expansion of subterms in the integrand. I was considering an unfortunate example such as,

    goo := Int( (1-cos(t)^2)*(1-sin(2*x)^2), x=a..b );
    IntegrationTools:-Expand(goo);

But if that kind of thing isn't causing you problems, then all the better.

ps. In your last Reply you seem to be using the word "summation" to refer to an explicit, finite sum of terms, ie. the result of explicitly adding a concrete, finite number of terms. That is not a good use of that word, especially since in your original Question you used around Sigma notation Sigma and a name n as upper end-point, for your query 1).

You wrote, "...using Expand does indeed make it possible to transform the inert integral of a summation into a summation of inert integrals."  But that's not true at all. Transforming an integral of a summation into a summation of integrals is the topic of your other query 1). The Expand command makes it possible to transform an integral of an explicit sum of terms into an explicit sum of integrals.

@GFY You haven't supplied your more complicated, explicit examples, so it's difficult to be sure about what difficulties you might have had with part 2.

It's not clear to me whether you are starting with the integrand in a state that is factored into f(t) and g(x) multiplicands, and whether the stock command attempts were just muddying up the integrand too much for easy recovery.

It's quite possible that a dedicated routine would be much better, once in f(t)*g(x) form. I mean, that could be a reusable, short proc -- something nice in an init file. Would that be useful?

1 2 3 4 5 6 7 Last Page 1 of 610