acer

32313 Reputation

29 Badges

19 years, 311 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are answers submitted by acer

Once expandoff is defined by the first invocation of,
   expand(expandoff());
then subsequent calls to expandoff() return NULL.

So your guess was not correct; it's not a scoping issue. Nor is it specific to the fact that your code lies within a procedure. Rather, it's due to the fact that the call expandoff() acts differently once the first call actually defines expandoff. Here we can see a similar effect occurring at the top-level:

restart;

expand(expandoff());

                 expandoff()

expand(expandoff());
Error, invalid input: expand expects 1 argument,
but received 0

So you need to prevent such a returned NULL value being passed along to the expand command.

One way is to first check whether expandoff() already returns NULL, and if it does then do not execute the statement,
   expand(expandoff());
That way worked for me, for repeated attempts on your example, but I don't show it here.

Another way is to put uneval quotes around it, ie.
   expand('expandoff'());

Below I show that way working on both a first and second call at dealing with the example expression. I also used a try..catch..finally so that the finally clause would provide a little more assurance that cleanup would get done. (I don't know whether you want cleanup done. Maybe you provided only a toy/partial example.)

restart;

foo:=proc(expr)
  local F;
  forget(expand);
  expand('expandoff'());
  expandoff(cos,sin,exp);
  try
    F:=expand(expr);
  catch:
    error lasterror;
  finally
    forget(expand);
    expandon(cos,sin,exp);
  end try;
  return F;
end proc:

expr:=(1+x)*sin(3*x+k);

          expr := (1 + x) sin(3 x + k)

foo(expr); # good

         sin(3 x + k) + sin(3 x + k) x

expand(expr):

    4*cos(k)*sin(x)*cos(x)^2-cos(k)*sin(x)+4*sin(k)*cos(x)^3-3*sin(k)*cos(x)+4*x*
    cos(k)*sin(x)*cos(x)^2-x*cos(k)*sin(x)+4*x*sin(k)*cos(x)^3-3*x*sin(k)*cos(x)

foo(expr);  # good

         sin(3 x + k) + sin(3 x + k) x

By the way, there are various alternative ways to prevent expand from expanding the trig calls. Here are two others:

restart;
expr:=(1+x)*sin(3*x+k):
frontend(expand, [expr]);

         sin(3 x + k) x + sin(3 x + k)

restart;
expr:=(1+x)*sin(3*x+k):
thaw(expand(subsindets(expr,specfunc({sin,cos,exp}),
                       freeze)));

         sin(3 x + k) x + sin(3 x + k)

If you are concerned with reducing verbocity perhaps you could consider removing the unnecessary subtypes and Or calls (which are all already within {...}),  and combining similarly structured types, etc. For example,

restart;

TypeTools:-AddType('my_type', '`*`'({rational, specfunc({sin,cos}),
                                     specfunc({sin,cos})^rational}));

type(3*sin(x)^2*cos(x)^(-3), my_type);

                true

type(sin(x)^2*99*cos(x), my_type);

                true

type(-4*sin(x)*cos(x), my_type);

                true

type(-cos(x)*sin(x)^(1/2), my_type);

                true

Explicitly, I think that,

'`*`'({rational, specfunc({sin,cos}),
       specfunc({sin,cos})^rational})

is considerably more legible, as well as easier to augment, than the following, because the words sin and cos appear few times.

''`*`'( { Or('specfunc'(sin),'specfunc'(sin)^Or(integer,rational)),
          Or('specfunc'(cos),'specfunc'(cos)^Or(integer,rational)),
          Or(integer,rational)})'

Also, having to nest uneval quotes is often a sign that some aspect could be improved. In your way of merely assigning the whole structured type to a name -- with extra quotes -- the ephemeral nature of uneval quotes is more apparent. If that assigned name accidentally got any unwanted extra evaluation then it could break. But by instead using AddType the minimal (and understandable) quoting is enough, and once the type is registered in the system some further inadvertant evaluation risk is avoided.

[edit] Another possibility is to create your own auxiliary type, whose handler procedure incorporates the combined test that you wanted to avoid when defining the structured type that you will later utilize. The auxiliary type is created just once, and it allows for multiple structured types to be created that might access it. The definition of the latter, structured type can is now even less verbose. And the words sin and cos appear just once, in a centralized way, making augmentation even easier. Eg,

restart;

TypeTools:-AddType('ratpow',(e,etype)->type(e,{etype,etype^rational}));
 
TypeTools:-AddType('my_type','`*`'({rational, 'ratpow'(specfunc({sin,cos}))}));

type(3*sin(x)^2*cos(x)^(-3), my_type);

                true

type(sin(x)^2*99*cos(x), my_type);

                true

type(-4*sin(x)*cos(x), my_type);

                true

type(-cos(x)*sin(x)^(1/2), my_type);

                true

If you wanted you could also make it more flexible, having the auxiliary type accept the type specification of the exponent (above, hard-coded as rational) as an additional argument. In that case perhaps the auxiliary could be named something like specpow instead of ratpow. For example,

TypeTools:-AddType('specpow',(e,etype,ptype)->type(e,{etype,etype^ptype}));
 
TypeTools:-AddType('my_type',
                   '`*`'({rational, 'specpow'(specfunc({sin,cos}),rational)}));

That second definition -- for my_type -- is now still short and quite understandable, but more flexible.

You wrote, "where (f@g)(..) cannot be written f(g(..))".

But your problematic case,
    ((max-min)/abs(Mean))(S);
is not actually of that stated, latter form.

Rather, your problematic case involves abs(Mean) applied to something, ie, like,
    abs(Mean)(..)
and so is more of the form
    f(g)(..)
rather than (as you stated) of the form f(g(..)).

The problem, then, is that your example involves f(g) where you apply f to g. That is not a syntax for composition of operators, and its result may not itself act like an operator. So the result of abs(Mean) may not act like an operator which could be applied to something in the way you want.

And nor is f(g)(..) a nested application of f and g to something.

What happens if you instead do it as either of these,

  plot(ta, 2000.0 .. 2030.0);

  plot('ta'(x), x=2000.0 .. 2030.0);

?

You are passing ta(x) to the `plot` command. That means that ta(x) will be evaluated before the plot command receives it as an argument, with `x` being an as-yet-unassigned name.

Your procedure ta might work fine if passed an actual numeric argument. But it can happen it goes wrong if ta is evaluted at a *symbolic* argument (name), followed by substitution of the numeric value for that name into whatever results.

This is a common difficulty, sometimes known as premature evaluation.

This is not specific to the name Digits.

That particular abbreviated syntax for entering floats (with the "e") requires a literal number for the exponent, not a name (whose value might be an integer). And that is all.

I realize that you are aware of several alternatives.

Your previous Question was about acting on a "whole expression" that was a sum of terms.

If this new Question thread relates to that (a sum of terms) as the another kind of relevant "whole expression" then that fact may dictate a course of action.

Here is a common approach to a related and somewhat common situation. (I cannot tell if it truly represents your situation, because you haven't fully described it.)

if type(expr, `+`) then
  select(type, expr, mytype);
elif type(expr, mytype) then
  expr;
else
  # Choose some appropriate
  # and meaningful fallback. Eg,
  0;
end if

You might wish to interchange positions of those first two conditions/actions.

But in general it may be quite innappropriate to make that `select` call (as Joe did,  following your cue) without knowing or checking that `expr` is something over which you'd want that action taken.

You might validly want `select` to act over the operands of `expr`, if it is a sum of terms. But otherwise that action might be inappropriate.

Ie. if `expr` were some other kind of multi-argument function-call then calling `select` on it might well produce a nonsensical result.

Just because expr is not of type mytype doesn't mean that it must be something (eg. a sum of terms) to which `select` can/should be appropriately applied. It could be a radical, or a special-function or trig call, etc. What's the sense in calling `select` on those beasts here, as fallback clause?

One problem here is that you are suppressing the output of the lines which assign to expr_1..expr_6. That prevents you from visualizing the ordering of multiplicands in the resulting product terms, which is part of the explanation.

The product subterms like, say, sin(x)*(1+x+x^2) are uniquified in memory. For efficiency Maple only stores one copy of this product (DAG). Its first creation specifies the ordering with which later instances are uniquified. If you subsequently enter (1+x+x^2)*sin(x) then that will be a reference to the (earlier) stored instance.

restart;

3+sin(x)*(1+x+x^2);

                       / 2        \
            3 + sin(x) \x  + x + 1/

3+(1+x+x^2)*sin(x);

                       / 2        \
            3 + sin(x) \x  + x + 1/

Another part of the problem is your particular choice of type. Compare with the following, which is not affected by the multiplicative ordering. Below, I force both orderings, and both succeed here.

restart;

3+sin(x)*(1+x+x^2);

                       / 2        \
            3 + sin(x) \x  + x + 1/

expr:=3+(1+x+x^2)*sin(x);

                       / 2        \
            3 + sin(x) \x  + x + 1/

select(type, expr,
       '`*`'({polynom(And(algebraic,
                          satisfies(u -> not has(u, I))),x),
              specfunc('sin')}));

                     / 2        \
              sin(x) \x  + x + 1/

restart;

expr:=3+(1+x+x^2)*sin(x);

                / 2        \       
            3 + \x  + x + 1/ sin(x)

select(type, expr,
       '`*`'({polynom(And(algebraic,
                          satisfies(u -> not has(u, I))),x),
              specfunc('sin')}));

              / 2        \       
              \x  + x + 1/ sin(x)

note: I didn't change the quoting within your inner types. It's not necessary to uneval-quote sin, as it's a protected name. But quoting specfunc may be prudent.

Perhaps another way to phrase it might be: it's not appropriate to use a noncommutative product type specification (in which ordering of multiplicands is specified) for a test on products in which commuting of multiplicands may occur.

[edit] There are related examples which may be of interest. The alternative I gave above does not guarantee that all the given types will appear in the products that are accepted, for more general examples.

Here's another example, and two other alternatives (which also allow for different orderings). The predicate in the last call to select allows only those products which contain exactly one multiplicand for each of the given types. And the middle select call requires that all the given types are represented.

restart;

3+sin(x)*x^2+x^4*sin(s)*cos(s)+x^6*cos(t):
expr_1:=3+x^2*sin(x)+sin(s)*cos(s)*x^4+cos(t)*x^6;

              2    4                  6       
  3 + sin(x) x  + x  sin(s) cos(s) + x  cos(t)

T := {polynom(And(algebraic,satisfies(u->not has(u, I))),x),
      specfunc('sin')}:

select(type, expr_1,'`*`'(T));

            2    4                  6       
    sin(x) x  + x  sin(s) cos(s) + x  cos(t)

select(u -> u::`*`
            and andmap(membertype,T,[op(u)]),
       expr_1);

                  2    4              
          sin(x) x  + x  sin(s) cos(s)

select(u -> u::`*` and nops(u)=nops(T)
            and andmap(membertype,T,[op(u)]),
       expr_1);

                           2
                   sin(x) x 

It's not clear from your very simple example whether in general your other examples of this task would each have their specified types cover disjoint classes of expression, or whether you are hoping to establish a 1-1 correspondence between the expressions (ie. multiplicands in a product) and the list/set of specified types. You should clarify that, though perhaps you consider that mention of pattern-matching in other related recent Questions by you might make it obvious(?).

As the error message indicates, the conditional check (of the `while` clause of the do-loop) cannot be tested if fs and de have not been assigned numeric values.

And, indeed, the very first iteration has that problem.

You could assign f(x0) to fs, and any concrete value greater than tol to de, just before beginning that while-do-loop.

Alternatively, you could use `until` to check at the end of the iteration, instead of using `while` to check at the start of each iteration.

I'll let you give it a shot, since it's likely homework. Let us know if you have further trouble.

If you right-click on a Slider then one of the choices in the drop-menu is "Edit Value Changed Code".

That is the code that will be executed whenever the Slider's position is changed manually, by sliding it with the mouse.

In the following attachment, I have made this be that code.

a := Pi/DocumentTools:-GetProperty("Slider0", ':-value');

DocumentTools:-SetProperty("TextArea0", ':-value', a);

When the mouse slider is moved manually then this code is executed. It does two things: it assigns Pi/(the new value) to the name a, and it writes the assigned value of a to another component that I'd inserted (a TextArea component).

CreatingSlider_ac_ac.mw

You can adjust that code as you see fit. You could have it assign to a, but not write to the TextArea component. Or you could use the value to write to the TextArea component without assigning to (or using) a separate variable such as a.

Another useful approach can be to have the component's action-code be a call to a user-defined procedure which you set up outside the component. But for now, perhaps it's best to focus on getting the basics of the control flow working.

note. I suggest that you refer to the identity of components as strings (here, "Slider0" and "TextArea0") as strings using double-quotes, not as names. I also prefer GetProperty/SetProperty over Do.

remark: in your original attachment you had  sin*(a) which is a multiplication, not a call to the sin command. I suppose that is an accidental syntax mistake.

You could look (again) at this prior Post.

note. I don't really understand why some people seem to prefer a graph that might not encapsulate at least as much detail as the dismantle command provides.

I also don't think that the more convenient layout for such a graph is one which splits each level horizontally.

restart;

ig := L*(1 - a^3/r^3)^(-1/2)/r:

eq := u = 1 - a^3/r^3:
IntegrationTools:-Change(Int(ig, r), eq, u);

      Int(-1/3*L/u^(1/2)/(u-1),u)

sol := eval(value(%), eq);

    2/3*L*arctanh((1-a^3/r^3)^(1/2))

diff(sol, r) - ig;

                    0

I used what seemed a reasonable candidate for a change of variables. I get the same final result (with different intermediates, of course) using u=a^3/r^3 or u=1/r^3 instead.

This seems to be a consequence of the 2D output typesetting in extended mode.

It doesn't happen for me if I first set (in a separate execution group from a restart),

   interface(typesetting=standard):

If you have a procedure that evaluates v__c(t) for any given numeric value of t, then there is no need for using point-probes (and I think that doing so in that case would be a relatively poorer approach, on several different grounds).

note: even in the less common scenario that the function for v__c(t) is not explicitly available (and, say, the original curve is obtained using the implicitplot command or similar), numeric rootfinding should still be possible for each known t-value.

Here is an example, using an invented operator for v__c(t).

plotting-ilines.mw

If you have only an expression for v__c, rather than an operator (procedure) then show us, and the adjustment should be straightforward.

The following considerations might be obvious to some people, but I'll spell them out anyway. I consider these advantages for someone learning Maple:
1) The solution is programmatic. After addition of additional t-value points, or a change to the definition of the plotted "function", the plotting code can be re-executed directly.
2) The various pieces (text-plots, dashed lines, etc) are on separate code lines for clarity, and each could be easily removed, adjusted, etc.

Shorter solutions are possible, although very terse approaches (eg. via more functional programming) are less legible and more difficult for the beginner to adjust.

I didn't put in cross-symbols at the intersection points. That would be a straightforward addition.

You mentioned linear regression in a few places. Perhaps you want something like these:

regr_3d2d.mw

pts:= Matrix([[19.8,12, 1.62],[24.7,14, 1.2],
                   [26, 16, 1.25],[35.1,20, 0.84],
                   [37.8,20.83,0.74],[10.8,9, 3.98],
                   [16.1,12, 2.46],[38.3,18, 0.52],
                   [24.5,16, 1.42],[15.8,11, 2.35],
                   [28.2,17.8, 1.19],[56.8,27, 0.37],
                   [25.4,17, 1.34],[29.3,18.1,1.12]]):
F3d:=Statistics:-LinearFit(a*x+b*y, pts, [x,y]);

       F3d := -0.210960256326733 x + 0.440339719466169 y

plots:-display(
  plots:-pointplot3d(pts,color=red,
                     symbol=solidsphere,symbolsize=12),
  plot3d(F3d,
         x=min(pts[..,1])..max(pts[..,1]),
         y=min(pts[..,2])..max(pts[..,2]),
         color=gray,style=surface,transparency=0.1),
  labels=[x,y,""], lightmodel=none, axes=box);

F2d:=Statistics:-LinearFit(a*x, pts[..,[1,2]], x);

                   F2d := 0.560023063311019 x

plots:-display(
  plot(pts[..,[1,2]],style=point),
  plot(F2d,
       x=min(pts[..,1])..max(pts[..,1])),
  labels=[x,y], axes=box);

 

For the explicit solution, my Maple 2021.1 can get the following,

restart;
kernelopts(version);

   Maple 2021.1, X86 64 LINUX, May 19 2021, Build ID 1539851

ode := diff(y(x),x)-y(x) = x*y(x)^(1/2):
ic := y(0)=4:
maple_sol_e := dsolve([ode,ic], 'explicit'):

odetest(factor(maple_sol_e), [ode,ic]) assuming real;

               [0, 0]

For the implicit solution, I wonder whether odetest might be utilized twice (bootstrapped)!?.

First 85 86 87 88 89 90 91 Last Page 87 of 336