Carl Love

Carl Love

28035 Reputation

25 Badges

12 years, 321 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are replies submitted by Carl Love

@perr7 For m=0, all the LaguerreL polynomials in your series are identically 1. Thus, this series is clearly equal to exp(1/x), not exp(x). Since exp(1/x) = exp(x) for x=1, it's a quite unfortunate choice as a test value for x.

@The function Note that the book answer has a factor like this: (1 + ... - 1). Those 1s cancel. If you distribute the coefficient, you get simply (1/2)*m__0*v^2, which Maple shows as the first nonzero term of the Taylor series.

The typeset formula that you hand-circled contains L(m, n-m, x), but the formula that you entered into Maple contains L(n, m-n, x). So, which formula do you mean?

@janhardo The example of comparing expressions in your most-recent Reply is much simpler than your earlier comparison. Since the argument of ln is identical in both expressions, the comparison is entirely based on trivial rules of precedence of multiplication and division. In other words, expr1 = A/B*C/D and expr2 = A/(B*D)*C where A = -IB = 2C = ln(...)D = b.

Your earlier comparison is essentially the same as comparing -ln((b+z*I)/(b-z*I)) with ln((b*I+z)/(b*I-z)).

@janhardo The double back quotes are used to introduce a pair of what I'll call "hard" parentheses, that is, parentheses that can't be removed by any normal mathematical simplification and which permanently separate what's inside them from from what's outside. The structure ``(...is viewed by Maple as a function; it's just like f(...except that nothing is displayed in front of the parentheses in the prettyprinted (2D) output.

I may have had the wrong idea about what you wanted. I originally thought that you wanted to display expressions in certain forms in 2D output. The Typesetting package offers extensive options for that, but it is awkward to use. The purpose of my module TS is to provide a few shortcuts to Typesetting to display the things that you've been asking about.

But now I think that you want to verify that expressions are mathematically equal, such as Maple's form versus your book's form. My module as well as the whole Typesetting package and 2D output itself are all worthless for that purpose.

Regarding the expression -I/2*ln((b + z*I)/(b - z*I))/b: It is NOT equal to the book's form for all complex z and b due to branch issues. As has been discussed extensively in other recent threads, some Maple simplification commands have a symbolic option that allows you to ignore those issues. Using that, the expressions can be shown to be equal, but you'd need to figure out the appropriate ranges for z and for which equality holds.

If you have expressions and that you want to verify are equal, it's much much easier to simplify A-B to 0 than to convert A into B. On the other hand, if you want to verify that they're not equal, the easiest thing is to usually to find numeric values of the variables for which they're not equal.

Regarding "splitting" an expression: Use the command op.

@AlexeyK Please let me know if you've been able to put any of these ideas into use, or whether you need further assistance and/or deeper explanations.

@janhardo Using the module TS from above, you can get your "book form" via

TS:-Mn(2):
TS:-Mn(i):
TS(i/(2*b))*ln(``(b*i+z)/(b*i-z));

And that can be reverted to Maple/math/active form via

subs(i=I, TS:-Value(%));

However, I think that you're also asking whether the "book form" can be produced via some automatic "simplification" process starting from Maple's output. No, because the book form has arbitrarily placed extra parentheses. There's no sensible and unambiguous rule that would place extra parentheses around b*i+z but not also around b*i-z or 2*b.

@Carl Love Here is some exposition of the "behind-the-scenes magic" that I referred to, as well as proof that the overridden method (move in this case) is a static export of the child class (dog in this case) distinct from its parent method (animal:-move), even though the method is not explicitly declared static in the child.

restart
:
animal:= module()
option object;
export 
    data1,
    move::static:= proc(_self, $) print("In Animal") end proc
;
end module:
 
#create class/module which extends the above
dog:= module()
option object(animal);
    move:= proc(_self, $) print("In Dog") end proc  
end module
:
Bear:= Object(animal):  Bear:-data1:= "bear":
Daisy:= Object(dog):  Jake:= Object(dog):
Daisy:-data1:= "beagle":  Jake:-data1:= "spaniel":
move(Daisy); move(Jake);
                            "In Dog"
                            "In Dog"
ToInert(Daisy);
_Inert_MODULE(_Inert_EXPSEQ(_Inert_ASSIGNEDLOCALNAME("data1", 
  "STRING", 36893491093222321372)), _Inert_MODDEF(
  _Inert_PARAMSEQ(_Inert_NAME("thismodule")), _Inert_LOCALSEQ(), 
  _Inert_OPTIONSEQ(_Inert_FUNCTION(_Inert_NAME("object"), 
  _Inert_EXPSEQ(_Inert_ASSIGNEDNAME("animal", "MODULE", 
  _Inert_ATTRIBUTE(_Inert_EXPSEQ(_Inert_NAME("protected", 
  _Inert_ATTRIBUTE(_Inert_NAME("protected"))), _Inert_NAME(
  "protected", _Inert_ATTRIBUTE(_Inert_NAME("protected"))))))))), 
  _Inert_EXPORTSEQ(_Inert_NAME("data1")), 
  _Inert_STATSEQ(_Inert_EXPSEQ()), _Inert_DESCRIPTIONSEQ(), 
  _Inert_GLOBALSEQ(), _Inert_LEXICALSEQ(), _Inert_EXPSEQ(), 
  _Inert_STATICLOCALSEQ(), _Inert_STATICEXPORTSEQ(
  _Inert_ASSIGNEDLOCALNAME("move", "PROC", 36893491093222288092))), 
  _Inert_EXPSEQ())

ToInert(Jake);
_Inert_MODULE(_Inert_EXPSEQ(_Inert_ASSIGNEDLOCALNAME("data1", 
  "STRING", 36893491093222321500)), _Inert_MODDEF(
  _Inert_PARAMSEQ(_Inert_NAME("thismodule")), _Inert_LOCALSEQ(), 
  _Inert_OPTIONSEQ(_Inert_FUNCTION(_Inert_NAME("object"), 
  _Inert_EXPSEQ(_Inert_ASSIGNEDNAME("animal", "MODULE", 
  _Inert_ATTRIBUTE(_Inert_EXPSEQ(_Inert_NAME("protected", 
  _Inert_ATTRIBUTE(_Inert_NAME("protected"))), _Inert_NAME(
  "protected", _Inert_ATTRIBUTE(_Inert_NAME("protected"))))))))), 
  _Inert_EXPORTSEQ(_Inert_NAME("data1")), 
  _Inert_STATSEQ(_Inert_EXPSEQ()), _Inert_DESCRIPTIONSEQ(), 
  _Inert_GLOBALSEQ(), _Inert_LEXICALSEQ(), _Inert_EXPSEQ(), 
  _Inert_STATICLOCALSEQ(), _Inert_STATICEXPORTSEQ(
  _Inert_ASSIGNEDLOCALNAME("move", "PROC", 36893491093222288092))), 
  _Inert_EXPSEQ())

ToInert(Bear);
_Inert_MODULE(_Inert_EXPSEQ(_Inert_ASSIGNEDLOCALNAME("data1", 
  "STRING", 36893491093222319868)), _Inert_MODDEF(
  _Inert_PARAMSEQ(_Inert_NAME("thismodule")), _Inert_LOCALSEQ(), 
  _Inert_OPTIONSEQ(_Inert_NAME("object")), 
  _Inert_EXPORTSEQ(_Inert_NAME("data1")), 
  _Inert_STATSEQ(_Inert_EXPSEQ()), _Inert_DESCRIPTIONSEQ(), 
  _Inert_GLOBALSEQ(), _Inert_LEXICALSEQ(), _Inert_EXPSEQ(), 
  _Inert_STATICLOCALSEQ(), _Inert_STATICEXPORTSEQ(
  _Inert_ASSIGNEDLOCALNAME("move", "PROC", 36893491093222287868))), 
  _Inert_EXPSEQ())

Note that the address of procedure move is the same for the two dogs, but different than the address of move in the animal.

@AlexeyK You wrote:

  • Concerning passing n: it's really a minor issue, but I caught myself on the thought that once you have evaluated the number of variables in the main procedure, it could be worth just assigning it to a variable and then passing it everywhere it is needed (thus, you don't need to evaluate the length again - a kind of optimality in terms of a number of operations). What do you think?

I agree, partially. The part that I agree with is that it's good to avoid recomputation. The part that I disagree with is that passing extra arguments is a good way to achieve that.

Maple has several ways to do it without passing extra arguments. Off the top of my head, the ways that I can think of are remember tables, Records, and objects. I'll describe remember tables, the easiest to use of those three.

A remember table is a component added to a procedure such that when the procedure is called with arguments with which it has previously been called, it automatically returns what it returned the last time without executing the procedure at all. This all happens behind the scenes; all that you need to do is add option remember to the procedure. So, for the case that we're talking about here, you can do this:

Arity:= 
    proc(f::procedure) option remember; nops([op](1, eval(f))) end proc
:
UV:= (f::procedure)-> 
    local x, y, XY:= map2(index~, [x,y], [$1..Arity(f)]);
    map(unapply, (evalc@[Re,Im]@f@op@(Complex@op)~)(XY), op~(XY))
:

@nm The validity of variable::type:= ... (including return-value) assertions other than for procedure parameters is checked if and only if assertlevel=2, and that checking is the only purpose of assertlevel=2. This checking must be done at run time rather than at compile (or parse) time, so it's expensive. In the case at hand, the move::static:= ... statement was in the body rather than the declarations of module dog, so, like all module bodies, it was executed immediately (which is why that code needs to be put in a ModuleLoad if the module is stored in a library).

@nm Sorry, I was undergoing a dental procedure when I sent the "Remove 'static'" message. I now see that this part may not have been obvious: I only meant for you to remove the 2nd static, the one in dog. This will work under assertlevel=2, and move will still be static because it's declared static in animal. Note that move is not being declared in dog; rather, the move that was already declared in animal is being reassigned. Through some behind-the-scenes magic that I don't understand, the dog object nonetheless retains a local copy of move.

@nm Try removing static.

@janhardo plotcompare does side-by-side plots. And, despite its somewhat generic name, it's specifically for complex functions. And two things you should know about its help page:

  • It's one of most-well-written and most-extensive help pages in all of Maple.
  • You'll learn a lot of complex analysis just from reading the help page, including how to find branch cuts on plots.

@pengcheng Xue So, using the variables already defined in your previous worksheet, the matrix to pass to approxsoln is simply

A:= <<s3[]> | s2>:

@AlexeyK 

I think that the most potentially confusing concept that the help page ?@ fails to illustrate adequately is that f@g also works when returns a sequence rather than a single value, provided that f is prepared to accept the number of arguments that g returns. In the example at hand, op is an operator that returns a sequence. The op in the subexpression Complex@op returns a pair (x[k], y[k]) for some between 1 and n, and Complex[*1] will accept two arguments. The op in the subexpression f@op returns exactly n values of the form Complex(x[k], y[k]), and f is expecting exactly n arguments. (We say that f is n-ary or that its arity is n.)

Recall from my Answer that I explained that it's not necessary to pass n. With the list-based functional-programming style that I've used, it's not even necessary to assign n as a local, its value being implicit as the length of list XY.

Footnote:
[*1] Complex(x,y) is almost the same thing as x+I*y, the difference here being that it'll remain unevaluated when x and y are just names. But, of course, it's handled sensibly by ReIm, and evalc or else it'd be worthless here. This distinction is not needed in procedure UV; I could just as well have replaced Complex with ((x,y)-> x+I*y)

First 104 105 106 107 108 109 110 Last Page 106 of 708