## 23454 Reputation

15 years, 359 days

## engineering notation...

Your example of 1.0*e7 is rather simple, and there are many trivial ways to render 10e6 based on 1.0e7 as input. Something more general could be useful.

I looked around some old worksheets and found the following for engineering notation of floats.

(The finesse of stripping trailing zeros -- one of several options below -- is based on a revision on some old code by Axel Vogt.)

In custom axis-tickmarks of the second and third plots below I show some additional formatting choices (which you could also use in formatting other float values for the legend).

```restart;
EN := module() local ModuleApply, Strip;
ModuleApply := proc(t::numeric,
{displayonly::truefalse:=true,
enotation::{truefalse,
identical(lowercase)}:=false,
showzeroexponent::truefalse:=true,
stripzeroes::truefalse:=true})
local m,mant,sgn,strip; uses InertForm;
strip := `if`(stripzeroes,Strip,x->x);
if t=0.0 then (m,mant,sgn) := 0,Strip(t),1;
else m := iquo(ilog10(t),3);
(mant,sgn) := Strip(10^(-3*m)*t),signum(t);
end if;
if showzeroexponent=false and m=0 then Strip(t);
elif displayonly then
if member(enotation,[true,':-lowercase']) then
nprintf("#mrow(mn(%a),mn(%s),mn(%a));",
`if`(mant=0.,"0.",
sprintf(sprintf("%s.%af","%",
length(op(1,mant/sgn))-ilog10(mant/sgn)-1),
mant)),
`if`(enotation=true,"E","e"),3*m);
else sgn*Display(mant/sgn%*10%^(3*m),':-inert'=false);
end if;
else mant*10%^(3*m);
end if;
end proc:
Strip:=proc(x)
local M,E,sM,smu,res; uses StringTools;
if x=0 then return x;
elif not type(x,float) then return x;
elif x < 0 then return -procname(-x) end if;
(M,E) := SFloatMantissa(x),SFloatExponent(x);
sM := convert(M,string);
smu := SubstituteAll(TrimRight(SubstituteAll(sM,"0"," "))," ","0");
res := SFloat(parse(smu),E+length(sM)-length(smu));
if res=trunc(res) then trunc(res) else res; end if;
end proc;
end module:

Lres := 1/((2*Pi*freq)^2*Cres):
ftest := 10e6:

plot(eval(Lres, freq = ftest), Cres = 0.0 .. 1e-9,
labels = [Cres, 'Lres'],
legend = EN(ftest),
color = red,
title = 'Inductance*Value*as*a*Function*of*Resonant*Capacitance',
axis = [gridlines = [default]], size=[600,300]);
``` ```plot(eval(Lres, freq = ftest), Cres = 0.0 .. 1e-9,
labels = [Cres, 'Lres'],
legend = EN(ftest),
color = red,
title = 'Inductance*Value*as*a*Function*of*Resonant*Capacitance',
xtickmarks = map(x->x=EN(x,enotation=lowercase),[seq(0.0..1e-9, 2e-10)]),
axis = [gridlines = [default]], size=[600,300]);
``` ```plot(eval(Lres, freq = ftest), Cres = 0.0 .. 1e-9,
labels = [Cres, 'Lres'],
legend = EN(ftest),
color = red,
title = 'Inductance*Value*as*a*Function*of*Resonant*Capacitance',
xtickmarks = map(x->x=EN(x,enotation=lowercase,showzeroexponent=false),[seq(0.0..1e-9, 2e-10)]),
ytickmarks = map(x->x=EN(x,enotation=lowercase,showzeroexponent=false),[seq(0.0..1e-5, 1e-6)]),
axis = [gridlines = [default]], size=[600,300]);
``` engineering_notation.mw

The attached worksheet contains a few more corner cases (testing), and a column-by-column table for visually easier comparision of optional effects.

There is room for improvement. When stripzeroes=false is specified then additional trailing zeroes appear -- so at present it can't be used to denote the concept of precision or extra significant-figures.

There are several pitfalls, where the regular typesetting mechanisms can interfere and undo part of some crafted solutions. But at least all this doesn't involve the poor mechanism of applying ``(...) and the ensuing italic font and unnecessary brackets.

## something...

You might play around with the colorscheme used in a densityplot of the complex argument of the function.

 > restart;
 > f := x -> x^3 + 3^x:
 > plots:-densityplot(argument(f(a+b*I)),                    a=-17..23,b=-35..35,                    grid=[401,401],style=surface,                    colorscheme=["zgradient",[white,red,blue]],                    labels=[Re(x),Im(x)],                    size=[700,400],axes=boxed); > plots:-densityplot(argument(f(a+b*I)),                    a=-17..23,b=-35..35,                    grid=[401,401],style=surface,                    colorstyle=HUE,                    labels=[Re(x),Im(x)],                    size=[700,400],axes=boxed); >

Another way to obtain the color image of that second example (the full hue range) is to rip the color substructure out of the complexplot3d result. This allow you to display it as an image instead of as a high resolution density plot, and so place much less burden on the GUI interface. (You may find that the GUI becomes slugglish when scrolling or saving, for the other approaches in this Answer which render plots.) Eg,

```restart;
f := x -> x^3 + 3^x:
H:=op([1,4,2],plots:-complexplot3d(f,-17-35*I..23+35*I,grid=[700,400])):
hsv:=Array(1..700,1..400,1..3,1.0,datatype=float):
hsv[..,..,1]:=360*H:
img:=ImageTools:-Rotate(ImageTools:-HSVtoRGB(hsv),90,':-degrees'):
plot(view=[-17..23,-35..35],background=img,
labels=[Re(x),Im(x)],
size=[700,400]);
ImageTools:-Embed(img);``` note: The background option to the plotting command is a little buggy (offset) in (only, so far) release Maple 2021.1.

Yet another way to do it as a density plot is to transform the complexplot3d result from 3D to 2D. This is an easy way to avoid some of the artefacts (due to undefined, say) in the earlier full hue densityplot result. Eg,

```restart;
f := x -> x^3 + 3^x:
Q:=plots:-complexplot3d(f,-17-35*I..23+35*I,grid=[700,400],
style=surface,size=[700,400]):
plottools:-transform((x,y,z)->[x,y])(Q);``` Your Question's title contains the wording, "...2D line type separating the real and imaginary parts". But I have considered reproducing the kind of plot colorings that you showed in your Question. If you really want to show only some curves/areas where the complex argument takes on only some finite number of values (or within epsilon of such) -- such as when the result is purely real -- then please respond and be very clear and explicit about the goal.

## suggestions...

fsolve(f(x)=g(x))

plot( [ Re(f(x)), Im(f(x)) ] )

## Q 2...

```f:=x->(x^2)-6*x+p+3: g:=x->(4*x^2)-(p-8)*x+7:

sol:=solve({ f(xf)=g(xg), D(f)(xf)=0, D(g)(xg)=0,
(D@@2)(f)(xf)>0, (D@@2)(g)(xg)>0 });

/                      -5\    /                     1\
{ p = -12, xf = 3, xg = -- }, { p = 12, xf = 3, xg = - }
\                      2 /    \                     2/

eval({f(xf),g(xg)},sol)[];

-18

eval({f(xf),g(xg)},sol)[];

6```

## something...

Maple's model of functional evaluation is inside-to-outside, and if you want to avoid some potential evaluation issues then I suggest reducing the inert operators from the inside out.

Here's an example, (based in part on this old code's idea). The inert=false option merely allows the output to render in the usual way, as opposed to the gray glyphs.

 > restart;
 > R := module() local f, T, S, ModuleApply;   T := And(function,            ':-satisfies'(f->evalb(convert(op(0,f),string)="%")));   S := t -> convert(convert(op(0,t),string)[2..],name);   f := X -> subsindets(X,And(T,satisfies(e->hastype([op(e)],T)=false)),                        t->S(t)(op(t)));   ModuleApply:=proc(X, {inert::truefalse:=true})     local res,old,temp;     old := X;     do print(InertForm:-Display(old,':-inert'=inert));       temp := f(old);       if temp=old then break;       else old := temp; end if;     end do;     return temp;   end proc; end module:

 > expr := 12 %/ (1 %- %abs(2%^2 %- (3 %- 1 %- 1%^2)%^2))         %+ %abs(-7) %/ %abs((x %- x) %- 2%^2)%^2:
 > InertForm:-Display(expr); > value(expr); > R(expr):         > R(expr, inert=false):         >

If you really want you can get the behaviour from the outside in, but something general has to be given up. You won't be able to use the inert form of every command (eg. fsolve), while retaining evaluation at each step. But if you're willing to allow inert forms of, say, just arithmetic operators and some simple things (that can return unevaluated) then something could be accomplished with recursion & state (operand list for position, and running expression) & subsop.

## automatic simplification...

Note that the construction of 2^(2/3)/2 from input 2^(-1/3) happens as a consequence of automatic simplification.

As such it cannot be prevented by delaying evaluation, eg. by use of uneval quotes, etc.

You may be able to use the inert operators such as %^, etc, to construct something that can be displayed as you want.

 > '2^(-1/3)'; > ee := 2%^(-1/3):
 > InertForm:-Display(ee, 'inert'=false); > Typesetting:-Typeset(Typesetting:-EV(ee)); At this point you may care to inform us of how the expression is first formed, ie. do you want to type it in, or is it a result of a computation.

## alternative...

If I understand the question properly, here are some alternatives you might consider.

The first one changes only how it gets normally pretty-printed. The second actually strips off the outer call.

You only have to define the procedure once per session, and you don't have to do some extra step each time you want to create or print an inert expression.

 > restart;
 > `print/%+` := proc()   if nargs=1 then args;   else '`%+`'(args); end if; end proc:

 > expr := `%+`(floor(5 %/ (2 %* 3 %* 5))); > expr; > InertForm:-Display(expr); > lprint(expr);

`%+`(floor(5 %/ ((2 %* 3) %* 5)))

 > `%+`(a,b,c); > lprint(%);

`%+`(a,b,c)

 > restart;
 > `%+` := proc()   if nargs=1 then args;   else 'procname'(args); end if; end proc:

 > expr := `%+`(floor(5 %/ (2 %* 3 %* 5))); > expr; > InertForm:-Display(expr); > lprint(expr);

floor(5 %/ ((2 %* 3) %* 5))

 > `%+`(a,b,c); > lprint(%);

`%+`(a,b,c)

 >

You might also do something similar for `%*`.

## integervariables...

The integervariables option of the LPSolve command allows you to specify (as a list) the names of the variables which must be integer-valued.

Eg,

```with(Optimization):

obj := -4*x-5*y:

cons := {x+3/2*y<=6, 5*x+4*y<=20, x>=0, y>=0}:

LPSolve(obj, cons,integervariables=[x]);

[-20.666666666666668, [x = 1, y = 3.3333333333333335]]

LPSolve(obj, cons, integervariables=[y]);

[-21.0, [x = 1.4999999999999998, y = 3]]

LPSolve(obj, cons, integervariables=[x,y]);

[-20, [x = 0, y = 4]]
```

## M=0 and M=1...

Your original attachment called implicitplot for first argument M (which implies M=0), and it called contourplot on first argument M with option contours= (which implies M=1). That's a mismatch in the values/heights of the contours/level-curves, which makes the comparison invalid, and which I've corrected below.

Below are plots for M=1 and M=0, each done with both those commands for comparison.

I used a larger initial grid option size, for implicitplot, and bumped down the gridrefine option's value.

The results basically match, between implicitplot and contourplot, except the latter's curves are coarser. The former is much faster and smoother. And the latter produces a coarser result even with a large grid value, that consists of a very large plotting structure that places considerable burden on the GUI.       Firstly, let's consider M=1.

 >  >   And now for M=0

 >  >   Here is a revision, done in Maple2016.2,

SDFFM_STAB_ac.mw

With your original grid=[5,5], gridrefine=8 some features/regions get missed. (Missed, I suspect, during initial analysis at the unfortunately-coarse initial [5,5], and hence subsequently also missed for refinement.)

In Maple 2021.1, by the way, the implicitplot command has some trouble with the very large (+/-) values of M, or with the severe slope, I suspect. That can be accomodated by an adjustment, to pass it, say,
max(min(M,2),-2) = 1
instead of just M=1. And similarly for M=0.

SDFFM_STAB_ac_2021.1.mw

## rationals, or floatPi=false...

These first two will not work directly in Maple 2015.2, but I'm going to mention them anyway since that version is getting quite out of date and some people might be interested in more current versions's behavior.

 > restart;
 > kernelopts(version); > expr := -.27059805007310*sin(.12+epsilon)         +.27059805007310*sqrt(1.-cos(.12+epsilon)^2); > kernelopts(floatPi=true):
 > simplify(convert(expr,rational)) assuming epsilon < Pi-12/100, epsilon > -12/100; > kernelopts(floatPi=false):
 > simplify(expr) assuming epsilon < Pi-0.12, epsilon > -0.12; Maple 2015 suffered from an additional weakness of needing a kick to get the trig identity applied. Here are two ways to do that kick, for each of the two approaches floatPi=true alongside rationals, and floatPi=false.

The approach below using freeze & thaw is an automation of a process to replace the sin & cos arguments temporarily with a symbol, which allows the trig identity simplification to succeed here. That's analogous to automating the steps subs(0.12 + epsilon=t, expr) and (potentially necessary) final replacement of t, in Kitonum's second approach.

For the applyrule apporach, note that the latter step involves simplify(...,trig) which succeeds, while simplify(...) without the option does not succeed in Maple 2015.2.

 > restart;
 > kernelopts(version); > expr := -.27059805007310*sin(.12+epsilon)         +.27059805007310*sqrt(1.-cos(.12+epsilon)^2); > kernelopts(floatPi=true):
 > thaw(simplify(subsindets(convert(expr,rational),specfunc({sin,cos}),                          u->op(0,u)(freeze(op(u)))))); > simplify(%) assuming epsilon < Pi-12/100, epsilon > -12/100; > applyrule(1-cos(p::anything)^2=sin(p)^2, convert(expr,rational)); > simplify(%, trig) assuming epsilon < Pi-12/100, epsilon > -12/100; > kernelopts(floatPi=false):
 > thaw(simplify(subsindets(expr,specfunc({sin,cos}),                          u->op(0,u)(freeze(op(u)))))); > simplify(%) assuming epsilon < Pi-0.12, epsilon > -0.12; > applyrule(1-cos(p::anything)^2=sin(p)^2, expr); > simplify(%, trig) assuming epsilon < Pi-0.12, epsilon > -0.12; Lastly, a note on why floatPi matters here. Consider the following effect.

 > restart;
 > kernelopts(floatPi=true):
 > epsilon < Pi - 0.12; > kernelopts(floatPi=false):
 > epsilon < Pi - 0.12; So, when floatPi=true (default) the inequality gets significantly altered. And in consequence some mixed floating-point & symbolic expressions can just be too much for the simplifier to recognize simplifications under mismatches due to roundoff error.

I used the particular formulation  epsilon<Pi-0.12  in above assumptions only because you had that in your Question. If you accept the formulation as  epsilon+0.12<Pi  and you replace that with a symbol then floatPi may not be relevant. Programatically picking off all arguments to sin&cos calls and freezing them may also get you those replacements. Earlier I used subsindets above on sin&cos calls, but indets can also work, also helping in programmatically generating assumptions.

So, as a more general and programmatic revision of one of my earlier four methods for Maple 2015,

 > restart;
 > kernelopts(version); > expr := -.27059805007310*sin(.12+epsilon)         +.27059805007310*sqrt(1.-cos(.12+epsilon)^2); > fcns := op~(indets(expr,specfunc({sin,cos}))): conds := map(u->(u>0,u In the case of multiple trig calls with differing operands you could handle contradictory generated assumptions, say by catching the relevent error thrown by assuming.

## order...     ## HeatMap, or Newton Fractal?...

I'm not really sure what you mean by "Polynomiograph".

Do you mean something like a Newton method iterative fractal image, which could be produced using the Newton command from the Fractals:-EscapeTime package? Suppose you wanted to use you given list of colors to shade the escape-time values for some polynomial.

You could use the Statistics:-HeatMap command for this.

First, let's see that that command acting on a small Matrix.

```restart;

m:= Matrix([[1, 2, 3], [4, 5, 6]]):

cm := ["aquamarine","blue","brown",
"coral","cyan","black"]:

#Statistics:-HeatMap(m,color=cm,axes=none,size=[600,400]);

Statistics:-HeatMap(m,color=cm,
axes=none,method=polygons,size=[600,400]);``` Now lets apply that command to the first layer results from the Newton command.

```with(Fractals:-EscapeTime):

bl, ur := -6 - 6*I, 6 + 6*I:

f := t^3 - t^2 - 12;

3    2
t  - t  - 12

temp := Newton(400, bl, ur, f, output=layer1):

cm := ["aquamarine","blue","brown",
"coral","cyan","black"]:

Statistics:-HeatMap(temp,color=cm,axes=none,size=[400,400]):``` That use of (undocumented) method=polygons is there as a workaround for a Maple 2021.1 bug in which the default background image (method=image) extends ouside the axes. That might not be appealing if you remove the axes=none option.

You might also look at the various ColorTools color Palettes, as there are some alternatives for your named colors.

It's also possible that you might want to color by the particular root to which each point might converge. If that's the case then you should explain clearly what you want and how you expect the colors to be used. I recall once implementing that in a few ways (densityplot+caseswitch+colorscheme, or IterativeMaps+caseswitch), but I'd have to try and dig them out.

## two ideas...

For now, you might change the (forced) order that the determinate functions appear in the list passed as second argument to dsolve.

```analytic_sol:=dsolve(sys, [Sy(t), Xc(t)]);

plot(eval([Sy(t), Xc(t)], analytic_sol), t=0..10);
```

Curiously, the alternative of using a set (rather than a list) also works. It seems to work even if the lexicographic set-ordering matches the list order that fails. (I rename, to illustrate.)

 > restart:
 > sys:=[diff(c(t),t) = - y(t),       diff(y(t),t) = -c(t) * (1  - c(t)^2),       c(0)=0, y(0)=1]:
 > simplify(dsolve(sys, [c(t), y(t)]));

Error, (in dsolve) numeric exception: division by zero

 > {c(t), y(t)}; > simplify(dsolve(sys, {c(t), y(t)})); > simplify(dsolve(sys, [y(t), c(t)])); >

## something...

If you have a problem with your particular example then it would be better to upload and attach your worksheet. That can also help with syntax issues.

Here I've squinted and tried to reproduce the input for the int call from your image, in plaintext Maple notation. I prefer to use a different name for the upper limit of integration.

 > restart;
 > kernelopts(version); > simplify( combine( int( -(C__A*K+1)/(k*C__A), C__A=C__A0..C__AA ) ), size )   assuming C__A0>0, C__AA>C__A0; ## various...

I'm not sure whether you are trying to simplify or improve the code you gave, or obtain code to produce a table of a variety of such curves.

Here, procedure L produces the curve for a particular set of parameter values, from t=0 to t=T some final value. You could call L with some choice of parameter values, to see that. Procedure LL makes a table of different calls to L, using names lists of parameter choices. And LL can be animated across T values. (There are several other ways you could code this, expecially w.r.t. you choice of parameters for a table. Adjust as you see fit.)

```restart;
dlist:=[0,1*Pi/4,2*Pi/4,3*Pi/4,4*Pi/4]:
ablist:=[[1,1],[2,1],[3,1],[3,2],[4,3],[5,3],[6,5]]:
L := proc(A,B,a,b,d,T) local ee,t; uses plots;
display(subsindets(
plot([A*sin(a*t+d),B*sin(b*t),t=0..T],
'color'="white",'thickness'=1),
'specfunc(:-anything,:-THICKNESS)',u->':-THICKNESS(0.9)'),
pointplot([A*sin(a*T+d),B*sin(b*T)],'color'="cyan",
'symbol'=':-circle','symbolsize'=6),
'axes'=':-none','scaling'=':-constrained',background=black);
end proc:
LL := proc(T) local i,j; uses plots, plottools;
(nops(dlist)-i+1)*3,(nops(abslist)-j+1)*3),
i=1..nops(dlist)),j=1..nops(ablist)),
'size'=[nops(dlist),nops(ablist)]*125,'axes'=':-none',
'scaling'=':-constrained','background'="black");
end proc:
## A single call to LL
#LL(2*Pi/3);
plots:-animate(LL,[T],T=0..2*Pi,'paraminfo'=false,'frames'=51,
'background'="black",'size'=[nops(dlist),nops(ablist)]*125);``` Lissajous_anim1.mw

The code above is slightly more verbose than necessary, so that a few possible modifications might be a little more clear. If you wanted to get fancier you could also color the curves according to certain parameter values, or add captions below each to show values.

As for the code you originally supplied, I think that merging a multitude of calls to plots:-animate makes the coding unnecessarily complicated. One difficulty it brings is that the various curves and points cannot be easily seen together (as a visual check of correctness) as a single frame for a single value of the animating parameter.

As an alternative approach, the procedure F below generates any single frame, taking the animating parameter as its sole argument. Thus a call to F generates a single frame, which makes for a much easier and quicker way to test that a given frame looks right.

Also, the various plot and pointplot calls could be merged. An easy edit, but a bit tidier.

 > restart;
 > with(plots):
 > base := display(plot([cos(x), sin(2*x),x=0..2*Pi], thickness=2),                 display(plot([cos(t),t,t=0..2*Pi]),                         plot([t,sin(2*t),t=0..2*Pi]), thickness=0)):
 > F := a -> display(base,   plot([[[0,sin(2*a)],[cos(a),sin(2*a)]],[[0,a],[cos(a),a]],         [[cos(a),sin(2*a)],[cos(a),a]],         [[cos(a),0],[cos(a),sin(2*a)]],[[a,0],[a,sin(2*a)]],         [[cos(a),sin(2*a)],[a,sin(2*a)]]], thickness=3,        color=[green\$3,red\$3], linestyle=[seq([solid,solid,dash][],1..2)]),   pointplot([[cos(a),sin(2*a)],[0,sin(2*a)],[0,a],[cos(a),a],              [cos(a),0],[a,0],[a,sin(2*a)]], color=[blue,green\$3,red\$3],             symbolsize=23, symbol=solidcircle)):
 > F(Pi/3); > animate(F, [a], a=0..2*Pi, frames=100); >

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