Carl Love

Carl Love

28085 Reputation

25 Badges

13 years, 96 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

The errors and/or warnings that you're getting come when you try to use indexing to add or modify an element in an existing list with more than a certain number of elements (I think the cut-off is 100 elements). In other words, any statement of the form L[k]:= ... will give this message if L is a list and has 100 or more elements. But note that this form of assignment statement is a bad thing to do even in the cases where Maple doesn't obstensibly object to it. It is also just as bad (for efficiency) to add elements to an existing list, set, or sequence without using indexing, although Maple (unfortunately) doesn't complain about it. Here are the 3 most common bad statements of this form:

L:= [op(L), x]; #adding to a list
S:= S, x; #adding to a sequence
S:= S union {x}; #adding to a set

Lists, sets, and sequences are three of the fundamental indexable container data structures of Maple. Those particular three are the immutable containers. (I'm omitting here any further discussion of containers with arithmetic properties such as explicit sums and products, although it's worth keeping in mind that these too are immutable.) All of these statements (including the explicitly indexed assignment) are bad because they don't truly modify the container; instead, they construct a new container from scratch by copying the old container plus the new element. Indeed, immutable literally means "can't be changed", and there's truly no way to change these containers. These statements are one of the main causes of inefficiency in Maple programs.

But Maple also has three fundamental indexable mutable containers: tables, rtables, and records. An rtable is a VectorArray, or Matrix. Tables can be explicitly created by the table command, or they're implicitly created by assignment statements of the form T[k]:= x where is a previously unused name (and and x can be anything, or even sequences of things, or even NULL). Records are created with the Record command; they're fairly specialized, so I won't discuss them further here.

One nice feature of all these mutable containers is that the elements in these containers can be anything at all, even lists, nested lists, sequences, or even NULL  (this underlined part is the direct answer to your specific question). So you can (and probably should) use a one-dimensional Array for the specific situation that you posed:

A:= Array(1..10, i-> [[0,0], 0]);

If you want to extend this Array to 11 elements, you may do this:

A(11):= ...; #note the ( ) instead of [ ]! 

or this is much easier (new to Maple 2018) because you don't need to know the last index:

A,= ...; #that's not a typo!

I recommend that you NOT use a two-dimensional Array for the situation that you described.

Using a table instead of an Array is comparably as efficient and avoids a lot of syntax:

T:= table(): #optional, although recommended.
for k to 10 do T[k]:= [[0,0], 0] od:
T[11]:= [[1,2], 3]: #must be [ ] after T!

There are no restrictions on table indices; unlike Array indices, they don't need to be consecutive integers, and indeed they don't need to be integers at all.

If you come to a point in your code where you no longer need to modify your table or Array (or add elements to it), it's perfectly fine and efficient to convert it to a list at that point. There are several ways. The easiest are these:

#Array A:
L:= [seq](A);

#table T:
L:= [entries](T, 'nolist'):
#or, if T contains "naked" sequences or NULLs this is better:
L:= [entries](T):

If you want your table elements to be listed in a certain order, you'll need to do something different, which isn't difficult, but it may be easier to use an Array in that case.

As of Maple 2019, it's possible to create lists, sets, and sequences of arbitrary non-predetermined length with do loops (forwhile, etc.) without using any of the "bad" statements that I discussed in the first two paragraphs and without any efficiency penalty. For example,

L:= [for k to 10 do [[k+1,k], k^2] od];

The outer square brackets make it a list. They could be changed to { } for a set or ( ) for a sequence. These loops have the full flexibility of any Maple code:

  • There's no limit to how much code is in the do loop.
  • It can be any code, including other loops and if statements. 
  • The length of the container need not be predetermined: The loop can be exited by a break statement or while or until condition.
  • These container-constructing loops can be embedded in other code anywhere the container itself can appear; they needn't be explcitly assigned to anything.

To my mind, these container-constructing do​​​​​​ loops are the greatest innovation in Maple since objects were introduced (in Maple 16, I believe). It's a shame that they're not more widely known, because they provide the easiest solution to the problems that I discussed in the first two paragraphs, which are very serious efficiency burdens.

The following procedure will be significantly faster (than even my modification of Kitonum's procedure) for numbers with many divisors:

SumOddDivisors:= proc(n::integer)
local k, q:= n;
    for k while q::even do q:= iquo(q,2) od;
    2^(k-1)*NumberTheory:-SumOfDivisors(q)
end proc
:  
#Example:
n:= 2^39*3*5*7*11*13*17*19*23*nextprime(2^29);
               n := 32922697295031156088441405440

CodeTools:-Usage(SumOddDivisors(n));
memory used=7.57KiB, alloc change=0 bytes, cpu time=0ns,
real time=0ns, gc time=0ns

                 82255314605128880924739502080

The reason that this is significantly faster is that the sum of the divisors of a number can be computed without computing the divisors themselves; only the factorization into prime powers is needed. Simple example: 81 = 3^4; the sum of its divisors is (3^5 - 1)/(3 - 1) from the well-known formula for a finite geometric sum.

Your equation can be easily converted to a polynomial, and this'll cause fsolve to use its dedicated polynomial algorithm, which often produces better results. However, the fundamental problem is still as acer says: You need to increase Digits because the root is so close to 1. But the polynomial technique may be beneficial to you for some other problems. 

Digits:= 16:
r2poly:= denom(rhs(r2))-numer(rhs(r2))/lhs(r2);
                              7                       2
         r2poly := (ksi + 100)  (ksi - 1) (2 ksi - 99) 

                                  5    5
            + 5.894442105097472 10  ksi 


fsolve(r2poly, ksi);
             -119.4197464595025, 0.9999999999994157


By default, all real roots are returned. The option complex could be added.

Note that xi will prettyprint as the Greek letter that you spell ksi​​​​​​.

So, why did you use option outliers= true?

I think this is what you want:

Statistics[BoxPlot](
    X, orientation= horizontal, deciles= false, mean= false,
    axis[2]= [tickmarks=0], view= [1..80, -.5..1.5]
);

There are two wedges that are bounded by those 3 surfaces: In one case, 0 <= z <= -y; in the other, -y <= z <= 0. Here's one way to plot them:

plot3d([1, theta, z], theta= -Pi..0, z= 0..-sin(theta), coords= cylindrical, scaling= constrained);
plot3d([1, theta, z], theta= 0..Pi, z= 0..-sin(theta), coords= cylindrical, scaling= constrained);

The only difference in those two commands is the range of theta.

If you examine the evaluated result of sqrt(x) with lprint, you'll see x^(1/2). Thus, it doesn't contain the literal expression sqrt. The command has is looking for the literal expression, whereas hastype and types in general allow for more subtlety.

P.S. In the title, I mean that sqrt(x) is not a function in the special sense that that word is used in Maple. Of course it's a function in the ordinary mathematical sense (as long as x is a free variable).

You can use solve to put the initial conditions into standard form:

ics2:= solve({ics}, {a0,a2,b0,b2,a1,b1}(0));
            /        3           3          3           15  
   ics2 := { a0(0) = --, a1(0) = -, a2(0) = --, b0(0) = --, 
            \        16          8          16          16  

             1          -1\ 
     b1(0) = -, b2(0) = -- }
             8          16/ 


dsolve({odes} union ics2, numeric);

It is NOT a solution. Perhaps you mean that z0(t) = t^2*exp(-t) is a solution? This can be verified with odetest:

z0:= t-> t^2*exp(-t):
ode:= diff(z(t),t,t)+2*diff(z(t),t)+z(t)=2*exp(-t):
odetest(z(t)=z0(t), ode);

                               
0

The return value 0 means that it's a solution.

According to its help, the 2nd argument to rgf_findrecur should be a list of 2*consecutive terms of the sequence, where K is the order of the recurrence (as well as the 1st argument). Presumably, extra terms are simply ignored.

Edit: I replaced with 2*K.

There's no point in using CodeTools:-Usage on some code that doesn't even work. To see that it doesn't work, remove the Usage command. The reason that Usage is obscuring that it doesn't work is because you've used output= bytesused, so the output is just that number rather than the result of your computation.

The vast majority of modules should not be packages. What benefit did you think you were getting by using option package? The only good reason (AFAIK) to use option package is if you want to load the module with with.

ComPoly:= proc(g, h, x::name)
local c, k, d:= degree(h,x)/degree(g,x), f;
    if d::integer then
        f:= add(c[k]*x^k, k= 0..d);
        eval(f, solve(identity(subs(x= g, f)=h, x)))
    fi
end proc
: 
ComPoly((x+1)^2, 2*x^4+8*x^3+13*x^2+10*x+6, x);
                             2        
                          2 x  + x + 3

 

You can combine non-indexed subscripting with concatenation like this

add(1/x__||i, i= 1..5)

This won't work with sum because sum evaluates its arguments before supplying the index values.

 

I am not saying in this Answer anything fundamentally different than what @nm said. I'm just rephrasing it because your Reply to that Answer indicates that you don't understand yet.

Here's your call to CodeTools:-Usage:

Usage(SOL[n+1], output = ['cputime', 'output', 'bytesused'])

The first argument, SOL[n+1]should be a call to the procedure that you want to measure. But SOL[n+1] is obviously not a call to a procedure because it has no parentheses.

The exact same thing applies to your other Question (now deleted) about the low and constant memory numbers.

Footnote (just for nitpickers): Yes, I know that the 1st argument doesn't need to be a procedure call. I said that it should be. In this case, the OP has no good reason for it not to be.

Great Question. Vote up.

It can be done with a small "surgery" on the plot structure after it's created to change the floats back to their corresponding fractions. Assuming G is your graph, is your plot structure, and all the weights were originally specified as explicit fractions (which is how you coded it), do this (there's no need to look at the plot first):

Fr:= table(
    sort([indets(P, And(string, float &under parse))[]]) =~
    sort([indets(GraphTheory:-WeightMatrix(G), fraction)[]])
):
subsindets[2](P, And(string, float &under parse), Fr, index);

First 77 78 79 80 81 82 83 Last Page 79 of 395