Carl Love

Carl Love

28055 Reputation

25 Badges

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

MaplePrimes Activity


These are answers submitted by Carl Love

Use

subsindets(p, patlist(0, anything), ()-> ());

This will remove any list (regardless of length) whose first element is 0. Of course, this is done without disturbing any other part of the structure.

I think that I can anticipate your next several questions, and I need to be away from the Internet for a few days. So, the code below will give you something to think about for a few weeks at the very least (and that would be if you study Maple all day, every day). But this code does seem to me to be the direction that you're heading.

The procedure below takes an unevaluated expression that can be evaluated at different levels (which I call a "cascade of evaluations" or "evaluation chain" or "evaluiation tree") and saves it as a vector of strings that can be used to reconstruct the entire cascade, even in a different Maple session, even on a different computer.

This uses some of the deepest non-mathematical concepts of Maple. It is a testament to the power and beauty of Maple that this can be done in such a short procedure.
 

restart:

(* Procedure SaveNameCascade: Takes a name (which could be the start of an
"evaluation cascade") and returns a Vector of strings which can be parsed
(even in another Maple session!) to reconstruct the cascade.

Some caveats:
1. Reconstructed names are always global, even if the originals weren't. There's
no way around this.

2. It's possible that there are assigned names that only appear in indices that
my indets commands below will not find. If there's demand for it, I can handle
that situation with more-complex (and recursive) indets commands.

3. It's possible to create expressions whose evaluation causes changes to the
assigned values of some names in the cascade; in other words, self-modifying
expressions. Indeed, it's quite easy to intentionally do that for the purpose of
creating bad examples. Obviously, the results of applying this procedure to such
expressions may be nonsense.

4. It's even possible to create expressions whose partial evaluation contains a
reference to the unevaluated original. Obviously, attempting to fully evaluate
these results in an infinite loop.
*)


SaveNameCascade:= proc(t::uneval)
option `Author: Carl Love <carl.j.love@gmail.com> 4-Oct-2018`;
local j:= 0, k, n, e:= t, v:= eval(t), R:= Vector(), Match;
   for k while e <> v do
      for n in
         indets(e, 'And'('name', 'Not'('indexed'), 'satisfies'(n-> n <> eval(n))))
         union
         map2(
            op, 0,
            indets(
               e,
               'And'(
                  {'function', 'indexed'},
                  'satisfies'(f-> op(0,f) <> eval(op(0,f)))
               )
            )
         )
      do
         if not assigned(Match[eval(n,1)])  then
            Match[eval(n,1)]:= ();
            j:= j+1;
            R(j):= cat(sprintf("assign('%a' = '%Q", n, eval(n,2)), "')")
         fi
      od;  
      e:= eval(e,2)
   od;
   R
end proc:
            

#Example #1:
A:= B:  B:= C:  C:= 7: #Construct a (single-path) evaluation cascade.
seq(eval('A',k), k= 1..4); #View it.

A, B, C, 7

R:= SaveNameCascade(A); #Save the cascade as a Vector of strings.

Vector(3, {(1) = "assign('A' = 'B')", (2) = "assign('B' = 'C')", (3) = "assign('C' = '7')"})

 A:= 'A':  B:= 'B':  C:= 'C': #Delete the cascade (and all sub-cascades).
eval~([A, B, C]); #Verify that it's deleted.

[A, B, C]

parse~(R, statement): #Rebuild the cascade from saved strings.
seq(eval('A',k), k= 1..numelems(R)+1); #View it.

A, B, C, 7

#Example #2: A more-intricate example of a branched-tree cascade, including
#an Array, reconstructed in another Maple session:
L:= [x[1,2], x[2,1]];  x:= Array(1..2, 1..2, (i,j)-> 2^i*3^j);
seq(eval('L',k), k= 1..3); #View it.

L := [x[1, 2], x[2, 1]]

Array(%id = 18446746286613268470)

L, [x[1, 2], x[2, 1]], [18, 12]

MySavedTree:= SaveNameCascade(L);

Vector(2, {(1) = "assign('L' = '[x[1,2], x[2,1]]')", (2) = "assign('x' = 'Array(1..2, 1..2, [[6,18],[12,36]])')"})

#You'll need to change this directory name to something appropriate
#for your computer:
currentdir("C:/Users/CarlJ/Desktop"):

save MySavedTree, "SavedTree.mpl";


#Start a new Maple session:

restart:

currentdir("C:/Users/CarlJ/Desktop"):

read "SavedTree.mpl";

Vector(2, {(1) = "assign('L' = '[x[1,2], x[2,1]]')", (2) = "assign('x' = 'Array(1..2, 1..2, [[6,18],[12,36]])')"})

parse~(MySavedTree, statement):
seq(eval('L', k), k= 1..3);

L, [x[1, 2], x[2, 1]], [18, 12]

 


 

Download NameCascades.mw

Like this:

algcurves[plot_real_curve]((x^2+y^2+2*y)^2 - 4*(x^2+y^2), x, y);

This only works for polynomials in two variables, but for such curves, this command gives much better results than other plotting commands.

Like this (is the simplest[1] way):

MaxAbs:= L-> max(abs~(L));
and its usage would be
MaxAbs(L1);

You can (and probably should) add some type protection, like this (just an example of many possibilities):

MaxAbs:= (L::list(complexcons))-> max(abs~(L));


[1]In some simple cases, such as this one, it is possible to create functions without using the arrow by building them from existing functions with functional operators such as @ (composition) and (elementwise). So,

MaxAbs:= max@abs~;

When this is possible, it is often (but not always) more efficient than using the arrow. 

The only official help for it that I can find is on page ?type,structure:

  • The type specfunc(t, n) matches the function n with 0 or more arguments of type t.  Thus, type(f, specfunc(t, n)) is equivalent to the logical conjunction type(f, function) and op(0,f) = n and type([op(f)], list(t)). Instead of a single name n, a set of names may be passed as the second parameter to the specfunc type constructor.  In this case, an expression matches if it is a function call with any of the names in the set as the 0-th operand. Thus, type(f,specfunc(t,{n1,n2,...,nk})) is equivalent to type(f,specfunc(t,n1)) or type(f,specfunc(t, n2)) or ... or type(f,specfunc(t,nk)).

That's pretty dense material, but if you have any specific questions about it, I have an expert-level understanding of it, so fire away.

The only thing that I can imagine that you're failing to see about it is that all arguments of the function must be of the specified type(s). So, consider your F: Because of the j, there is no occurence of u with all arguments of type `+`.

If you're only interested in type-checking u's first argument, we can work on that; there are a few options. Also note that specfunc does nothing to control the number of arguments; u() will pass through all of your typespecs, and the transformer will then fail because it requires op(1, ...).

And I suppose that you already know that {type1, type2} is the union of those types.

Unrelated issue: You could (I'm not saying should) replace your transformer that uses subsop with

f-> applyop(`+`, 1, f, 1);

There's no efficiency benefit (as of Maple 2018) to doing this, since applyop simply translates it back to what you had with subsop, which you can see via showstat(applyop). I just think that it's a bit cleaner with applyop.

 


 

There are two ways to get the name, strictly speaking: evaln(x) or 'x'. Those are forward single quotes, and they're known in Maple as unevaluation quotes or delayed evaluation quotes. They're very commonly used, but evaln is not. There's a slight distinction between the two: The quotes can be used on anything, but evaln requires an underlying name.

The way that you posted (using double quotes) indicates that you might want the name as a string. In that case, you still need to use one of the options from the first paragraph, and then convert to a string:

convert('x', 'string');
or
convert(evaln(x), 'string');

The quotes on string are not strictly necessary in this case. I just wanted to show you how unevaluation quotes are commonly used. They protect against the possibility that you've assigned a value to string (probably unintentionally).

I'll suppose that the above set is named Sols. Then all you need to do is eval with respect to Sols and then use assign, like this:

Sols:= {R = 7.339698158, S = 2.378491488, W = 2.512047349}:
assign(eval([X=R, Y=S], Sols));

The assign command displays no output, but if you look at X and Y, you'll see that they're the desired numbers.

The commands printf and print cause stuff to be displayed on your screen. In a trivial sense, this could be considered "output", but, as you've noted, it's not usable. Ordinarily, this is a common rank-newbie error, but considering the way that the exercise's instructions are given on RosettaCode, the author made a reasonable choice. A procedure's true output, or return value, is set by a return statement, or more usually as the last expression evaluated. Here's a procedure that does what you want:

splitChange:= proc(str::string) 
local start, i:= 1, len:= StringTools:-Length(str), R:= table();
   while (start:= i) <= len do
      for i from start to len do until str[i] <> str[start]; 
      R[start]:= str[start..i-1]
   end do;
   [entries(R, 'indexorder', 'nolist')]
end proc:

 

That's a very interesting discovery. The strange thing to me is not that the bond is lost in the second case, but that the bond exists in the first case. If the bond continued to exist in the second case, that would be a mystery akin to quantum entanglement.[*1]

I notice that you're saving to Maple-internal-format .m files. Apparently, that format retains the information that items share a memory address. If you change to a plain-text format by using any filename other than *.m, then the strange bond disappears.

But the issue has absolutely nothing to do with tables or eval, so it'd be helpful if you retitled this Question. Here's an illustration using simple name variables:

restart:
A:= B: B:= x:
currentdir("C:/Users/CarlJ/Desktop"):
save B, A, "FC.m"; #Note: B, A; not A, B!
restart:
currentdir("C:/Users/CarlJ/Desktop"):
read("FC.m");
B:= y:
A;
                               y

[*1]Come to think of it, suppose that this were being run on two quantum computers. The files containing A and B, respectively, are created on computer Q1. File B is sent to computer Q2, and it's read there. Is it possible that the bond could be maintained?

Change cat(elemt) to parse(elemt). The help page does not say that the element name / symbol can be a string, although I'd agree that a string should be allowed.

f:= (t,y)-> -y + t*y^(1/2);
diff(f(t, y(t)), t);

It simply can't be done for an Array (note the distinction with array), and I don't see why you'd want to do it. An Array's entries always have a value. That value may be NULLundefined, etc., but those are still values.

Look at the last few characters of your description:

 `digits"`;  

If this doesn't make the problem obvious already, then I'll explain further.

You didn't show your failed attempts, so I can't really diagnose what you were doing wrong. But the most-obvious command works for me:

subs(sqrt((n__x^2 + n__y^2 + n__z^2)*c^2)= phi, X);

Perhaps you entered n[x], etc., instead of n__x?

The simplest thing that you can do is use a higher value of Digits, which will affect the accuracy of all internal computations. The following gives a perfect plot. A lower value of Digits might also work, but I didn't try.

f:= x-> exp(x)*HeunC(2*x, 1/2, -1/2, -x^2, 1/8, 99/100):
Digits:= 30:
plot(f(x), x= 0..40);

Of course, using more Digits takes more time. If you need a way to do repeated high-speed computations with this function, we can work on that.

First 161 162 163 164 165 166 167 Last Page 163 of 395