acer

32343 Reputation

29 Badges

19 years, 328 days
Ontario, Canada

Social Networks and Content at Maplesoft.com

MaplePrimes Activity


These are replies submitted by acer

@Carl Love Vote up.

I think that the extension mechanism requires an actual procedure, which can be wrapped around an appliable module. (It's also possible that you tried that as a second attempt, but neglected to clear the remembered result.)

restart;

kernelopts(version);

`Maple 2018.0, X86 64 LINUX, Mar 9 2018, Build ID 1298750`

 

SimplifyIntervals:= module()
local
   x::identical(x),
   ModuleLoad:= ()->
      TypeTools:-AddType( #recursive type: put base cases 1st!
         'RealIntervals',
         Or(
            specfunc(RealRange),
            set(realcons),
            'specop'('RealIntervals', {`intersect`, `union`, `minus`})
         )
      ),
   Deconstruct:= (IN::RealIntervals)->
      if IN::specfunc(RealRange) then convert(x::IN, relation)
      elif IN::set(realcons) then Or((x =~ IN)[])
      elif IN::`minus` then And(thisproc(op(1,IN)), Not(thisproc(op(2,IN))))
      else `if`(IN::`union`, Or, And)(map(thisproc, [op(IN)])[])
      fi,   
   ModuleApply:= proc(IN::RealIntervals)
   local pts, ints;
      (pts,ints):= selectremove(type, [solve(Deconstruct(IN), x)], realcons);
      `union`(sort(ints, key= (p-> `if`(op(1,p)::realcons, op(1,p), op([1,1],p))))[])
            union {pts[]}       
   end proc
;
   ModuleLoad()
end module:

 

expr := (((RealRange(-infinity, 1) intersect RealRange(Open(-1), infinity))
           minus RealRange(-1/3, 1/3)) minus {0}) union {-2,2};

`union`(`minus`(`minus`(`intersect`(RealRange(-infinity, 1), RealRange(Open(-1), infinity)), RealRange(-1/3, 1/3)), {0}), {-2, 2})

 

`simplify/intervals` := SimplifyIntervals:
forget(simplify);

 

simplify(expr, intervals); # Does not use the appliable module

`union`(`minus`(`minus`(`intersect`(RealRange(-infinity, 1), RealRange(Open(-1), infinity)), RealRange(-1/3, 1/3)), {0}), {-2, 2})

 

`simplify/intervals` := proc() SimplifyIntervals(args); end proc:
forget(simplify);

 

simplify(expr, intervals); # Uses the procedure

`union`(RealRange(Open(-1), Open(-1/3)), RealRange(Open(1/3), 1), {-2, 2})

 

Download simplify_intervals.mw

How about uploading a worksheet that let's us explicitly see (or experiment with) your example?

@Spirithaunter After making the replacements I suggested throughout I no longer see that error message at all.

Spirithaunter_01.mw

Please upload a worksheet that reproduces the problem.

@vv I tried to give the OP some advice about not using unapply (and a procedure call) when an expression would serve. That is enough to avoid the problem.

But the originally exhibited problem is deeper, I think. In the examples below, what is the essential difference between Vectors boo and rah? Why does mapping eval across rah have such an effect, while applying rtable_eval (to rah, or V, or anything in sight, with or without its inplace option) does not have a similar effect?

I agree with you that the construction was unusual. It seems like advice might include: don't unapply a Vector and then subsequently change that Vector's entries.

restart;

kernelopts(version);

`Maple 2018.0, X86 64 LINUX, Mar 9 2018, Build ID 1298750`

V := Vector(2);

Vector(2, {(1) = 0, (2) = 0})

f := unapply(V, t);

f := proc (t) options operator, arrow; Vector(2, {(1) = 0, (2) = 0}) end proc

V[1] := t^2;
V[2] := t^3;

t^2

t^3

rah:=f();

Vector(2, {(1) = t^2, (2) = t^3})

lprint(eval(rah,1));

Vector[column](2, {1 = t^2, 2 = t^3}, datatype = anything, storage = rectangular, order = Fortran_order, shape = [])

K := unapply(rah,t);

K := proc (t) options operator, arrow; Vector[column](1 .. 2, {1 = t^2, 2 = t^3}, datatype = anything, storage = rectangular, order = Fortran_order, subtype = Vector[column]) end proc

K(3); # like the OP's problem

Vector(2, {(1) = t^2, (2) = t^3})

boo := map(eval,rah);

Vector(2, {(1) = t^2, (2) = t^3})

lprint(eval(boo,1));

Vector[column](2, {1 = t^2, 2 = t^3}, datatype = anything, storage = rectangular, order = Fortran_order, shape = [])

L:=unapply(boo, t);

proc (t) options operator, arrow; rtable(1 .. 2, {1 = t^2, 2 = t^3}, datatype = anything, subtype = Vector[column], storage = rectangular, order = Fortran_order) end proc

L(3);

Vector(2, {(1) = 9, (2) = 27})

lprint(eval(K,1));

proc (t) options operator, arrow; Vector(2, {(1) = t^2, (2) = t^3}) end proc

lprint(eval(L,1));

proc (t) options operator, arrow; rtable(1 .. 2, {1 = t^2, 2 = t^3}, datatype = anything, subtype = Vector[column], storage = rectangular, order = Fortran_order) end proc

 

Download Vector_unapply_oddity.mw

@student_md Suppose you have an expression already, involving the global name t. And then you construct a procedure (operaotr) using just the arrow notation directly. The parameter t of the procedure (operator) is different from the global name t inside the expression. They look the same, but they are quite distinct. When the procedure is called it uses the value of it argument wherever that name is used in the body of the procedure. But in the following example the parameter t does not occur in the expression (since that contains just the global name t).

restart;

expr := t^2;

                        2
               expr := t 

p := t -> expr;

            p := t -> expr

p(2.1);

                    2
                   t 

This is a frequently asked question. Here are some ways to make it work. Note that :-t is a useful syntax for referring to the global name t, and distinguish it from a parameter or local name t.

expr := t^2;

                            2
                   expr := t 

r := unapply(expr, t);

                             2
                  r := t -> t 

r(2.1);

                      4.41

s := subs(dummy = expr, t->dummy);

                              2
                   s := t -> t 

s(2.1);

                      4.41

w := t -> eval(expr, :-t = t);

          w := t -> eval(expr, :-t = t)

w(2.1);

                      4.41

As you can see, unapply provides one convenient way to construct a procedure from an expression.

Try not to overuse unapply. It can be inefficient to have a procedure F that calls unapply each time you call F. Another way is to use 2-argument eval to evaluate an expression at a value for a name. Eg,

expr := sin(x)*exp(x):
eval(expr, x=2.1);
                                 7.049114358

Also, never bother to create a procedure with unapply if you're only going to just call it with a name for its argument. You may as well just use the expression. Eg, here's something I see now and then,

restart;
expr := sin(x)*exp(x):

f := unapply(expr, x):
plot(f(x), x=0..Pi);   # this is silly, if it's the only time f is used.

plot(expr, x=0..Pi);   # one could just as easily do this

Also, don't try and use a function call on the left-hand-side of an assignment statement, unless you really know what you're doing. That was part of your original difficulty in your Question. That's complicated.

And so you could avoid the original problem simply by following the advice to not create a procedure (with some parameter name) and then only use it with a function call to the same unassigned name, or the advice to not assign to a function call.

This adjustment makes it almost identical to my answer.

restart;
C :=[[0,1/11],[1/11,1/9],[1/9, 1/7],[1/3,1/2],[1/2,1]]:
C1:=map(t->x>=t[1] and x<=t[2], C):
op(map(`[]`@op,[solve(`or`(C1[]))]));

               [0, 1/7], [1/3, 1]

@student_md Yes, the MatrixSystem is not linear in the c[i] so it makes no sense to try and use GenerateMatrix (let alone linsolve or LinearSolve).

Even if it were linear for another example, its a mistake to re-assign to lowercase b since that's being used for the x-range lower endpoint.

ps. Did you edit the original Question and remove material?

I see that Kitonum already gave essentially the same answer, while I was still typing. The only difference being that I converted the RealRange results from solve into lists (just to match the OP's input of a sequence of lists).

Note: RealRange can prettyprint like a list. I don't know whether the OP prefers lists, or is not aware of the RealRange structure.

So, another variation, if say we started with a sequence of RealRange rather than a sequence of lists.

restart;

C :=map(RealRange@op,[[0,1/11],[1/11,1/9],[1/9, 1/7],[1/3,1/2],[1/2,1]])[];

                 /   1 \           /1   1\           /1  1\  
   C := RealRange|0, --|, RealRange|--, -|, RealRange|-, -|, 
                 \   11/           \11  9/           \9  7/  

              /1  1\           /1   \
     RealRange|-, -|, RealRange|-, 1|
              \3  2/           \2   /

solve(Or(op(map(r->convert(__dum::r,relation),[C]))));

                         /   1\           /1   \
                RealRange|0, -|, RealRange|-, 1|
                         \   7/           \3   /

@student_md Obtaining the min and max depends on the kind of plot, yes.

If you upload an example with a different kind of plot or coloring scheme then we can show you how its data can be handled to get a corresponding colorbar.

@minhthien2016 I edited my Answer to illustrate that.

I suggest that you tell us what shading/coloring scheme you want to accomplish.

For example, would you be content with shading by hue, as the (z-value) height changed?  Eg,

num_sol:-plot3d(x=0..1, t=0..1, shading=zhue, grid=[79,179], style=surface);

num_sol:-plot3d(x=0..1, t=0..15, shading=zhue, grid=[79,879], style=surface);

And here is a variant where the burden is not on the user to specify the z-height contour values up front.

I consider that as a useful case. It's never quite satisfying when a nifty use of contour plots requires the user to figure out in advance what contour values to use. It's nice that we can force the values, but many users will prefer the system try and do it.

I've been wanting this for some time, and realized that I can now get it easily by ripping it out of the hover-over contour label substructures that plots:-contourplot now produces. (It's a little weird that I didn't think of this earlier, as I've used the info in those new substructures for other cool things.) I've never liked the idea of averaging the values obtained by substituting CURVE x-y data points into the formula.

And the contours on the upper 3D surface are rendered by the GUI from the CONTOURS substructure rather than from CURVE substructures (which very often look jagged and either too thick or too thin, alongside a surface).

In summary: the precise contour values are the same for the 2D density + contour plot as they are in both 3D surfaces. And the color shading is also exactly the same.

These plots look much better in the actual Maple GUI than they do when rendered inline by this site's backend.

restart;

# Allow `contourplot` to choose the z-heights for contours.
#

C2D:=plots:-contourplot(sin(x)*y^2, x=-Pi..Pi,y =-1..1,
                        color=black, contourlabels=true):

 

# Grab the z-heights used from the contour-label hover-over substructure.
# This is nicer than kludging an average of substitutions of the CURVE points.

Clist:=[map[2](op,1,indets(C2D,specfunc(anything,_HOVERCONTENT)))[]];

[-.777, -.555, -.333, -.111, .111, .333, .555, .777]

# Standalone 3D surface, with same contour values.
#
# Re-use that z-heights list in `contours` options. This makes the
# GUI responsible for rendering the 3D contours purely from a terse
# CONTOURS substructure, and that looks much better tightly next to
# the rendered surface than would any CURVEs transformed from 2D up
# to the surface.
#

P := plots:-contourplot3d(sin(x)*y^2, x=-Pi..Pi, y=-1..1,
            contours=Clist,
            thickness=1,
            colorscheme=["zgradient",
                         ["Red","Orange","Yellow","Green","Cyan","Blue","Magenta"]]):
P := subsindets(P,specfunc(anything,STYLE),()->STYLE(PATCHCONTOUR));

# Standalone 2D densityplot, with same contour values and shading.
#
# Here is the 2D filled contour plot.
#

plots:-display(
  PLOT(op([1],P),STYLE(PATCHNOGRID)),
  C2D
);

# And now, combine 3D, with all same z-heights for contours.
#

zval := -1.1:  # choice of height of horizontal surface
lowerP := subsop([1,3]=Matrix(op(2,op([1,3],P)), zval, datatype=float[8]), P):

plots:-display(
  P,
  lowerP,
  plottools:-transform((x,y)->[x,y,-1.1])(C2D)
);

 

Download 2d_3d_filled_contours.mw

 

@Carl Love A 2D contour plot (un-filled) can be combined with a 2D density plot of custom shading. The "2D density plot" can be constructed using plots:-densityplot or via plots:-surfdata(...,dimension=2,style=surface).

If using surfdata then the GRID data from a plot3d result can be re-used. And if you're willing to assemble the plot structure manually (or subsop) then even the very same RGB COLOR data from a plot3d(...,colorscheme=...) may be re-used I believe.

But, if the goal is only to insert the filled 2D contour plot as a lower, horizontal plane in the final, combined, 3D plot, then couldn't you just take a plot3d surface, shaded via with colorscheme, and map it down to the plane? And likewise map the 2D contours (explicit data) up to the upper surface.

Ie. Don't use style=surfacecontour for the plot3d upper surface. It's a pity that plots:-surfdata doesn't allow style=surfacecontour alongside dimension=2. I am supposing that it's nice to have the exact same x-y contour positions, as well as the same color shading.

[edited] Here are some of the ideas I was trying to convey.

restart;


# First variation: raising 2D CURVEs via plottools:-transform.
# The resulting 3D curves look a little graining against the surface.

P := plot3d(sin(x)*y^2, x=-Pi..Pi, y=-1..1,
            style=surface,
            colorscheme=["zgradient",
                         ["Red","Orange","Yellow","Green","Cyan","Blue","Magenta"]]):
P;

# 2D density plot
PLOT(op([1],P),STYLE(PATCHNOGRID));

lowerP := subsop([1,3]=Matrix(op(2,op([1,3],P)), -1.1, datatype=float[8]), P):

lowerP;

plots:-display( P, lowerP );

C2D := plots:-contourplot(sin(x)*y^2, x=-Pi..Pi, y=-1..1,
                          color=black, thickness=2):

plots:-display(
  P,
  plottools:-transform((x,y)->[x,y,sin(x)*y^2])(C2D),
  lowerP,
  plottools:-transform((x,y)->[x,y,-1.1])(C2D)
);

restart;

#
# Second variation: Using style=patchcontour on the upper surface.
# This makes the contour curves render better alongside the surface.
#

P := plots:-contourplot3d(sin(x)*y^2, x=-Pi..Pi, y=-1..1,
            contours=[-0.75,-0.5,-0.25,-0.1,0.1,0.25,0.5,0.75],
            thickness=1,
            colorscheme=["zgradient",
                         ["Red","Orange","Yellow","Green","Cyan","Blue","Magenta"]]):
P:=subsindets(P,specfunc(anything,STYLE),()->STYLE(PATCHCONTOUR));

# 2D density plot
PLOT(op([1],P),STYLE(PATCHNOGRID));

C2D := plots:-contourplot(sin(x)*y^2, x=-Pi..Pi, y=-1..1,
                          contours=op(indets(P,specfunc(anything,CONTOURS))[1]),
                          color=black, thickness=1):

plots:-display(
  PLOT(op([1],P),STYLE(PATCHNOGRID)),
  C2D
);

lowerP := subsop([1,3]=Matrix(op(2,op([1,3],P)), -1.1, datatype=float[8]), P):

lowerP;

plots:-display(
  P,
  lowerP,
  plottools:-transform((x,y)->[x,y,-1.1])(C2D)
);

#
# A third variation is possible, where the lower horizontal surface
# also has style=patchcontour. That'd be even easier, for building the
# full 3D assembly, as no explicit CURVE structures would be needed.
# But the 2D combine plot would still need explicit CURVE structures, since
# unfortunately the PATCHCONTOUR style is not accepted by the GUI for 2D. (bah!)
# I recall the a Mapleprimes member also wanted the 2D contour plot separately.
#

 

Download densityplot_from_3dsurface.mw

@Christopher2222 OK, I think I see. You are also using 2D Input mode for your example.

So, in the writeto file, the output shows in prettyprint=1 form, but the input shows as Typesetting code.

If you also want the input sent to file as 1D Maple Notation then you'll need to toggle to 1D Input mode in an Execution Group (as well as set interface(typesetting=standard) ).

I will submit a few bug reports:

  • There ought to be no need to set interface(typesetting=standard) when using writeto in the GUI. This seems a regression, now that extended is the default.
  • Using writeto in the GUI, setting interface(prettyprint=0) produces output that is wrongly wrapped in a Typesetting:-mprintslash call. And that is not avoidable even if also setting interface(typesetting=standard) .
  • It's not clear what 2D Input should produce when using writeto a file from the GUI. Personally I can imagine it as possible a useful way to debug 2D Input mode. But it's also just a barrier.
  • These subtleties aren't all documented in the Help page for writeto .
First 237 238 239 240 241 242 243 Last Page 239 of 592