acer

32787 Reputation

29 Badges

20 years, 127 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@JoyDivisionMan It also produces the value zero 0 if assuming t<=0.

It would be nice if int(..., allsolutions) were able to handle this example directly.

So (while using supports of RVs might be one way, especially in this simple arithmetic combination), one can also split at the problematic value t=0.

But t::real can be handled as well, (if stepping in to deal with t=0), eg.

with(Statistics)

x := RandomVariable(Uniform(1, 2))

y := RandomVariable(Uniform(2, 3))

 

combine(piecewise(t <= 0, `assuming`([PDF(x*y, t)], [t <= 0]), t >= 0, `assuming`([PDF(x*y, t)], [t >= 0])))

piecewise(t <= 2, 0, t <= 3, ln((1/2)*t), t <= 4, ln(3/2), t <= 6, -ln((1/6)*t), 6 < t, 0)

Download MultiplyPDFFunctions_acc.mw

ps. I don't see why this might be considered any more ad hoc than using conversion via ln (which doesn't alone work for all examples...). Problematic t-values might possibly be found programmatically, though as mentioned it'd be nice if int handled it directly via allsolutions.

Sometimes I prefer workarounds like applying ln (since it's terse and easy to try), and sometimes I prefer ones which (I suspect) might give me additional insight into how things might get improved directly/automatically.

@RafalAblamowicz 

Do the commands use limit, or int, or solve? If so then they may well be not thread-safe, since those Library commands are not.

The list of Maple commands which are documented as thread-safe is not huge (relative to the total number of commands).  Many of those which are are very low-level, and quite a few are kernel builtins as opposed to higher level Library commands.

I don't know of a general tool for determining whether a procedure does or calls anything which in is thread-unsafe. Having a global effect, or calling a thread-unsafe command, is a typical way to be itself thread-unsafe. And there are quite a few ways that can occur. You could try ThreadSafetyCheck from the CodeTools package, but I don't its full strength. I suspect I might be much more inclined to trust it flagging unsafety than safety.

There is option lock which can be put on a procedure. But if you put that on all your procedures then benefits of multi-threading can easily vanish, as it could prevent most or all parallel execution. There is also,
    ?multithreaded,threadlocaldata
as a Help topic, if you have a module whose procedures write to any module locals when run.

There are lots of weird ways for a procedure to be thread-unsafe. The sort command itself may be thread-safe, but its effects on reordering terms in an expression may not be.

An parallelization alternative to Threads is (sometimes) the Grid package. The latter dispatches individual computations to separate spawned Maple engines/kernels, and communication between child&parent kernels is explicitly controlled. But it can be less versatile.

On what basis do you believe that the procedures in your package are thread-safe?

@Carl Love That is nice and crisp.

notes: I believe that it requires Maple 2019 or later, which of course is no problem as the OP is using Maple 2025.

The example relates to an earlier question the OP has about contour plotting. It's doubtful that the OP's table has very many more entries than one might usually have as separate contour values. So I doubt that the efficiency difference for such a modest number of indices makes for a significant efficiency concern.

If you're interested, you can also do it in a loop.

The seq way is nice because it's a 1-liner. It extracts all the indices and then re-references (separately) back into the table to get each associated value. The loop way allows you to extract each index alongside its associated value.

restart;

T := table([ (a,b)=S1, (c,d)=S2, (e,f)=S3, (g,h)=S4 ]):

 

# first way
new1 := table([map(tt->tt[1]=T[tt[]],[indices(T)])[]]):

 

# second way
new2 := table():
for ind,val in eval(T) do
  new2[ind[1]] := val;
end do:

 

eval(T);

table( [( a, b ) = S1, ( g, h ) = S4, ( e, f ) = S3, ( c, d ) = S2 ] )

eval(new1);

table( [( g ) = S4, ( c ) = S2, ( e ) = S3, ( a ) = S1 ] )

eval(new2);

table( [( g ) = S4, ( c ) = S2, ( e ) = S3, ( a ) = S1 ] )


Download nm_table_q2.mw

@nm That is an interesting weakness in plots:-contourplot and in plots:-implicitplot, that it may fail to show the contour for value 0 for your latest followup expression ln(y^2 + 1), if the y-range is y=-1..1 instead of, say, y=0..1.

Please see the attachment, which is revised to better handle empty data. (My Answer's code inherited weakness in this regard Carl's revision of Kitonum's original.)

CPL05.mw

ps. The code in my Answer has been updated again, with this. I find from experience that it's less confusing for readers (down the road, or years from now) if they don't have to read all the Replies and deduce which contains the "latest".

@janhardo Well, you appear to have re-used Kitonum's useful interpretation and formula for the individual frames.

And your code also does repeated augmentation of a sequence, which is a technique that can be unnecessarily inefficient (a higher order of memory use, including more temporary garbage to collect). You've used a similar technique in other code in other Question threads, I've noticed (sometimes with iterated augentation of lists). This can be a bad thing if there are a great many elements and if they are somewhat large. I don't know whether this is a coding technique preferred primarily by you or by some AI engine that you're using to generate the code.

I mean code that looks something like,
    result := result, newitem
or,
    res := [res[], newitem]
Sometimes that can be done instead by using seq rather than a loop. Alternatively, sometimes it can be done with table-entry assignments in the loop, followed by conversion to list after the loop.

@nm Thanks, I've revised the code in my answer (a small but key edit of one word).

@nm That's interesting. The code I wrote works fine on all those followup examples in my Maple 2024.2.

But plots:-contourplot is behaving differently in Maple 2025.

Consider the following example. In M2024.2 in shows 9 contours, as expected. In M2025.1 it shows only 8 contours, lacking near x=-6. (I may have to submit a bug report on that.)

plots:-contourplot(cos(2*x), x = -2*Pi .. 2*Pi, y = .4 .. 1.4,
                   contours = 9,
                   contourlabels = false, colorbar = false,
                   view=[-6.2..-4.8,default]);

I have edited the code in my Answer, to handle your three follow examples above.

@sand15 I didn't see that as one of the OP's original queries, but OK. (Nice, but not the only way.)

@C_R I expect that some or all of that handling of pretty-printing procs&operators -- in typesetting=extended mode -- is coded within the Typesetting module itself.

And the default for interface(typesetting) switched from standard to extended a few years ago. At the same time some special function pretty-printing flipped from being off to being on, even within the typesetting=extended behavior, eg. BesselJ no longer pretty-prints a subscripted J, unless one enables it with Typesetting:-Settings or its assistant. Some of that is an aside. My point is that the behavior of Typesetting changes, now and then.

It's possible that the rules for 2D rendering of multiplication in pretty-printed proc body reside in more than one place, and that the handling of regular procs vs the handling of operator procs might have gotten inconsistent revision at some point, perhaps even accidentally. Just a guess.

@C_R Note that the dots are shown within the pretty-printing of the body of an operator, as opposed to an actual expression or regular procedure.

A procedure without option operator,arrow doesn't get this 2D effect upon printing. But operators do, and that's what unapply constructs.

interface(typesetting);

extended

f1 := proc(x) a*b*c*x; end proc;

proc (x) a*b*c*x end proc

f2 := x -> a*b*c*x;

proc (x) options operator, arrow; a*b*c*x end proc

f1(x);

a*b*c*x

op(3, eval(f2));

operator, arrow

subsop(3=[operator,arrow][], eval(f1));

proc (x) options operator, arrow; a*b*c*x end proc

unapply(f1(x), x);

proc (x) options operator, arrow; a*b*c*x end proc

op(3, eval(%));

operator, arrow


Download operator_prettyprint.mw


[Edit] It's interesting. The option operator alone makes the procedure body get pretty-printed in 2D. Adding the option arrow to that gets the dots for pretty-printing of multiplication.

interface(typesetting);

extended

proc(x) a*b*c*x; end proc;

proc (x) a*b*c*x end proc

proc(x) option operator; a*b*c*x; end proc;

proc (x) option operator; a*b*c*x end proc

proc(x) option operator,arrow; a*b*c*x; end proc;

proc (x) options operator, arrow; a*b*c*x end proc

proc(x) A*B*C*Int(f(y),y=0..x); end proc;

proc (x) A*B*C*(Int(f(y), y = 0 .. x)) end proc

proc(x) option operator; A*B*C*Int(f(y),y=0..x); end proc;

proc (x) option operator; A*B*C*(Int(f(y), y = 0 .. x)) end proc

proc(x) option operator,arrow; A*B*C*Int(f(y),y=0..x); end proc;

proc (x) options operator, arrow; A*B*C*(Int(f(y), y = 0 .. x)) end proc


Download operator_prettyprint_2.mw

@Andiguys You could add,

   labels=[i__2, d]

to your plot p (or plots:-display calls). Names as labels get pretty-printed by default.

If you have already assigned to those names, and if you also want to guard against unwanted evaluation after printing or re-using the plots --  possibly after subsequently assigning to either of those names -- then you could instead use,

   labels=[InertForm:-Display('i__2'),InertForm:-Display('d')]

Question_1_regional_acc.mw

 

You're welcome.

@nm You can deal with those too.

I suspect that you'll have seen such programming finesses before.

restart;

f := x+y+undefined+z+gamma+Pi+a+integrate+lasterror;

x+y+undefined+z+gamma+Pi+a+int+lasterror

indets(f,And(name,Not(constant))) minus {integrate,lasterror};

{a, x, y, z, undefined}

indets(f,And(name,Not({constant,identical(integrate,lasterror)})));

{a, x, y, z, undefined}

Download indets_name_2.mw

Note that some of the special names may have assigned values. (I doubt that you'd have many expressions containing those unevaluated, but if you do you can eval(f,1), use right-ticks, etc, which is almost getting off-topic...)

And you can also utilize the aforementioned depends aspect with those. I included the int(f(s),s=0..t) addend because I suspected that your original example might not be as general as you might want. But I don't (yet) know what would be your trickiest example.

@nm You wrote, "The bug has since been fixed in Maple, but I kept the above code just in case to be safe."

That is serious overkill. A misjudged performance killer. It's poor like always calling int with method=_RETURNVERBOSE, or running under assertlevel=2, for big sets of jobs which will get their performance evaluated.

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