Carl Love

Carl Love

28160 Reputation

25 Badges

14 years, 8 days
Himself
Wayland, Massachusetts, United States
My name was formerly Carl Devore.

MaplePrimes Activity


These are answers submitted by Carl Love

The following short code will convert your L into a Maple matrix of your specified form:

L:= [[[1,2],3], [[1,3],4], [[1,4],4], [[1,7],7]]:
ExMat:= <<` A ` |` B `>, <<(``@op)~(L[.., 1])> | <L[.., 2]>>>;

I don't know about the ability of Excel to accept this form. It may be that conversion to strings will be needed, as Tom did. If so, that conversion can be just as easily done to the ExMat created above. I wrote this Answer primarily because the above ExMat may be sufficient for you to do whatever you want to do directly in Maple.

Code notes: 

  1. ``@op is a composed operator (with @ being the composition operator (see ?@)) that converts a list into an equivalent form with "hard" parentheses. Technically, this form is called a function by Maple, with the function's name being the empty name ``. The commands expand or op will return the underlying sequence, which'll also make the parentheses disappear. Unlike in a list, in a vector or matrix a "naked" sequence (i.e., one without parentheses) can be a single entry. If this is fine for your purpose, you can simplify (``@op) to just op, which is the most-basic deconstructor of Maple objects (and likely the most commonly used Maple command with an alphabetic name).
  2. <... | ... | ... > is a constructor of row vectors, and also a columnwise constructor for matrices when its arguments all have the same number of rows.
  3. < ..., ..., ... > is a constructor of column vectors, and also a rowwise constructor for matrices when its argument all have the same number of columns.
  4. If there's ambiguity between operators 2 and 3 because there's no |s and no commas, then it's 3. If LL is a list (possibly containing sublists) then <LL> forms the column vector of the entries. So, this implicitly removes the outer (only) level of [ ] that make LL a list.
  5. Operators 2 and 3 can be arbitrarily nested; I believe that the result is always either a vector or a matrix, and that these operators cannot be used to build higher-dimensional arrays.
  6. ~ is the elementwise operator (see help page ?elementwise). 
  7. Just like a matrix, a list of lists can be multi-indexed as shown: L[.., 1]; however, if this were done on a large scale, it's not as efficient as it is for a matrix.
  8. When the "naked" (i.e., with no apparent operands) range operator .. is used as an index, it refers to the entirety of the dimension corresponding to its position. In some other languages (Matlab, Python), a colon is used for this purpose. I think that this is the only Maple infix operator that can be used "naked". Technically, when it's used like this, the operands are NULL, which can also be represented ().
  9. `...` is the symbol-forming operator, which is used to include non-alphanumeric characters in a symbol. In this case, I used it to pad the A and B with spaces. This serves two purposes (in this case): 1) display formatting, and 2) it protects against the possibility that A or B have been assigned values. Maple symbols are similar to strings, the main differences being 1) symbols can be assigned values, and 2) the two types may display differently, although the exact nature of that difference depends on where they're being displayed. 

Perhaps you should rethink your data structures. Why use an Array in the first place? I can't say for sure without knowing more details of your application, but from all that you've said so far, I think that a table would work better for you. 

If you change 0.5*X1 + 0.5*X2 to (X1+X2)/2, then it'll work without needing any change to Digits. This'll also work for Beta(5,5) and Beta(10,10).

Here is a procedure for it. The procedure is a tour de force of Maple structured-type programming, which is a somewhat esoteric topic, so it may be difficult to understand. The main idea is that by converting derivatives to D form, the order is easier to determine.

specdifforder:= proc(
    e, o::type, u::{name, function, set({name, function})}:= {}
)
local
    O:= {`if`(o::set, o, {o})[], identical(D)},
    U:= identical(
        `if`(
            u={},
            indets(e, function(name)),
            ((S,R)-> indets(e, specfunc(S)) union R)
                (selectremove(type, `if`(u::set, u, {u}), name))
        )[]
    ),
    Op:= ()-> curry(op, args),
    uT0:= And(
        U,    
        Not({specfunc(D), specop(`@@`) &under Op(0)}) &under Op(0)
    ),        
    uT:= And(
        U &under (f-> op([0, ..], f)(op(f))),
        Or([O], O &under nops) &under [Op([0, 0, ..])]
    ),
    R:= {}      
;
    if 0::O then R:= indets(convert(e, D), uT0) fi;
    R union indets(e, And(specfunc(diff), uT &under (convert, D)))
end proc
:
#Examples
e:= 
     diff(u(x,y),x,y) + diff(u(r,s),r,r) + u(x,y) + diff(u(x,y),x) + 
     diff(u(x),x) + diff(u(x),x,x)
:
specdifforder(e, 0, u);
                                  {u(x, y)}
specdifforder(e, 0);
                                  {u(x, y)}
specdifforder(e, 1, u);
                    / d         d            d         \ 
                   { --- u(x), --- u(r, s), --- u(x, y) }
                    \ dx        dr           dx        / 

specdifforder(e, 1, u(r,s));
                                / d         \ 
                               { --- u(r, s) }
                                \ dr        / 
specdifforder(e, {0,1}, u);
                / d         d            d                  \ 
               { --- u(x), --- u(r, s), --- u(x, y), u(x, y) }
                \ dx        dr           dx                 / 

specdifforder(e, 2);
                  /  2          2              2          \ 
                  | d          d              d           | 
                 < ---- u(x), ---- u(r, s), ------ u(x, y) >
                  |   2          2           dy dx        | 
                  \ dx         dr                         / 

specdifforder(e, 2, u(x));
                                 /  2      \ 
                                 | d       | 
                                < ---- u(x) >
                                 |   2     | 
                                 \ dx      / 

specdifforder(e, 2, {u(x), u(r,s)});
                          /  2          2         \ 
                          | d          d          | 
                         < ---- u(x), ---- u(r, s) >
                          |   2          2        | 
                          \ dx         dr         / 


 

The portion of the time used to construct the matrices and vectors is insignificant compared to the portion used for the integration. To see that this is true, in your initialization section include the line

unprotect(int):  int:= 1:

And make the last line of the worksheet 

time() - timer1;

Then execute the entire worksheet using the !!! on the toolbar. Doing this, I get about 1 second. 

Why do you set Digits:= 16? I can see no point in using a value greater than 15 (the cut-off for hardware-float computation) for this computation.

If the matrix and vector construction time were an issue, a small time reduction could be made by replacing 

Matrix(M+1, M+1, (j0,j)-> ...)

with

rtable((M+1)$2, (j0,j)-> ..., datatype= hfloat, subtype= Matrix)

and replacing

Vector(N, i-> ...), et al.,

with

rtable(N, i-> ..., datatype= hfloat, subtype= Vector[column])

So, just change your 2nd-to-last line to 

B:= subs(x= M - k, B) + O(k^2)

Your x and y are bound variables; the value of the integral doesn't "depend" on them; indeed, the value of the integral is constant. Perhaps you intended for the upper limits of integration to be variable?

This is a mathematical issue. There's no problem with how you wrote the integral (or wrote anything else). Indeed, your syntax is perfect.

B:= Matrix(parse(A))

What you point out is unfortunate; keywords should be global. What I usually do will help you avoid some of the typing. As you probably know, I almost never use the with command. But I do often assign the package name to a short variable. Thus

LAG:= LinearAlgebra:-Generic:
LAG:-Determinant[Q](A, method= LAG:-BerkowitzAlgorithm); 

Some other hints, in addition to Tom's:

  1. a) One way to construct the set A is A:= {seq}(2*k-1, k= 1..1000).
    b) However, it's not actually necessary to construct A to answer the question.
  2. An integer n is triangular iff 1+8*n is square.
  3. Boolean property checks: The following Boolean commands check properties of integers. By Boolean, I mean that they return true or false:
    a) issqr(n) checks whether n is square.
    b) isprime(n) or n::prime checks whether n is prime.
    c) n::odd checks whether n is odd. (If you solve this problem with 1a, this isn't needed.)
  4. a) Boolean properties can be combined with the Boolean operator keywords and, or, not, implies, and/or xor.
    b) (Optional) Given Boolean properties B1 and B2, they can be combined as B1 or B2. This can be extended to any number of properties. Any of the Boolean operators in 4a can used, in any combination.
  5. The subset of a set A that have property B can be formed by select(B, A).
  6. The number of elements of a set A can be counted by nops(A).

Using the above information, there are several ways that the problem can be solved with a single line of code.

The following (amazingly short) procedure processes a multiple-graph file of the form that you posted in a followup Reply:

  1. The graphs can be directed or undirected.
  2. They can contain self loops.
  3. They can contain isolated (disconnected) vertices.
  4. The vertices need not be sequentially numbered; any form of vertex name allowed by GraphTheory will work.
  5. Because of point 4, there's no need for the vertices to be listed in any particular order.

The required file format is exactly as the file you posted:

  1. Each graph begins with a name (any text will work) on its own line. Executing the procedure causes the resulting Graph to be assigned to this name.
  2. Graphs are seperated by a single blank line. No other blank lines are allowed.
  3. Each vertex is listed on its own line, followed by a colon, followed by a space, followed by a space-delimited list of its neighbors. Any space is allowed to be multiple spaces.

The output is a pair of lists:

  1. The first list is the names of the graphs (in string form so that they're inert).
  2. The second list is the Graphs.
restart
:
ReadGraphs:= proc(FN::string)
uses ST= StringTools, GT= GraphTheory, FTT= FileTools:-Text;
local 
   `&<`:= curry, `&>`:= rcurry,
    String:= (':-string', s-> parse(s[`if`(s[-1]=":", ..-2, ..)])),
    G:= ST:-Split~(ST:-StringSplit(FTT:-ReadFile(FN), "\n\n"), "\n"),
    S:= op~(1,G), N:= nprintf~("%s", S),
    VE:= ([(op~)~ &< 1, ([op]~)~ &< (2..)] @ subsindets &> String)(
        ([ST:-RegSplit]~)~("[ ]+", [op]~(2.., G))
    )
;
    assign(N=~ GT:-Graph~(VE[])); 
    (S, eval(N))
end proc
:
file:= "C:/Users/carlj/desktop/GraphData.txt":
(Names, Graphs):= ReadGraphs(file);
Names, Graphs := ["Graph1", "Graph2", "Graph3", "Graph4"], 
  [Graph 1: an undirected unweighted graph with 25 vertices and 50 edge(s),
   Graph 2: an undirected unweighted graph with 25 vertices and 50 edge(s), 
   Graph 3: an undirected unweighted graph with 25 vertices and 50 edge(s), 
   Graph 4: an undirected unweighted graph with 25 vertices and 50 edge(s)]

plots:-display(`<|>`(GraphTheory:-DrawGraph~(Graphs, title=~ Names)));
#Plot output omitted because I don't know how to post array plots on MaplePrimes.

 

Like this:

DrawSpaceCurve:= (
    fnc::And(list(algebraic), 3 &under nops),
    Evals::list(name= complexcons), 
    xr::(name=range(realcons))
)->
    plots:-spacecurve(eval(fnc, Evals), xr, _rest)
:
DrawSpaceCurve([x, y, x^2*y], [y=2], x= -5..5, color= blue, axes= frame);

 

Verify:= proc(n::And(odd, positive, Not(1)))
local s;
    for s from 0 to isqrt(iquo(n,2))+1 do
        if isprime(n-2*s^2) then return true fi
    od;
    false
end proc
:
for n from 3 by 2 to 9000 do 
    if Verify(n) then next 
    else printf("Failure for n=%d", n); break
    fi
od
:
Failure for n=5777

To see all failures, simply remove break.

The above can be made a little bit more efficient, at the expense of a bit of clarity. I'll post a followup. Note that my code doesn't use any sequences or lists; however, that approach isn't bad either. Though the one thing that I don't like about it is that it requires foreknowledge of the upper limit (the 9000 in this case).

Note that there are far more primes than squares. Thus, in Verify, it's more efficient to iterate over the squares and check primality than to iterate over the primes and check squareness.

The contourplot command works for parameterized surfaces. You just need to make the function a 3-list instead of a 3-vector:

Ennep:= [u - u^3/3 + u*v^2, v - v^3/3 + v*u^2, u^2 - v^2]:
plots:-contourplot(Ennep, u= -2 .. 2, v= -2 .. 2);

The list form is more convenient for most purposes, including your original plot3d.

In your worksheet, you've made two definitions of (or assignments to) A:

  • (A1): A:= n -> w*int(V*cos(w*n*t), t = 0 .. pw)/Pi:
  • (A2): A:= Vector(Ns, n -> F(n)):

I think that the best solution to your problem woud be to use some variable other than A for the second definition.[*1] That completely corrects the problem. However, it's also very important that you understand the reason why your original code led to the erroneous result: It's a subtle order-of-evaluation issue, and many such issues occur in Maple code (and also other symbolic-computation languages). In between definitions (A1) and (A2), you've made two definitions that directly refer to A:

  • (F1): f(t):= a/2 + sum(A(n)*cos(w*n*t), n= 1..100) + sum(B(n)*sin(w*n*t), n= 1..100);
    It's important to view the output of the above line to see that Maple has interpretted it as if you had entered
    f := t -> a/2 + sum(A(n)*cos(w*n*t), n= 1..100) + sum(B(n)*sin(w*n*t), n = 1..100);
    I recommend that when you define a function, you use the form f:= t-> ... rather than f(t):= ... because Maple will not always interpret the latter as the former, and whether this reinterpretation happens is crucial for the rest of this discussion.
  • (F2): F:= n -> sqrt(A(n)^2 + B(n)^2);

The fact that you've made two definitions ((F1) and (F2)) with direct references to A is immaterial here; what I'm about to say would still apply if you had made one or any other number. The crux of the matter is which definition of A, (A1) or (A2), is being used. It would be natural for you to think that (A1) is used because (F1) and (F2) are defined before (A2) is defined. But this isn't what happens. When a function is defined with the arrow -> (or with proc (see below)), its symbols (such as A, B, and w---and even the library symbols sin, cos, sqrt, and sum; and even the kernel symbols +, /, *, and ..!) use whatever definition is in effect at the time that the function (f or F in this case) is used rather than at the time that it was defined.  Thus, your usage F(5) that returns 0.7... is using (A2). This interpretation of the symbol A is called its evaluation, and I'll assume that you can now understand why this overall crucial issue is called the order of evaluation. There are several ways to change the order of evaluation; however, since it's not necessary for you to do so in order to correct your problem, and since I've just taught you a huge paradigm shift into symbolic computation, I won't overload this Answer`those concepts.[*2]

There's another issue that doesn't currently cause a problem, but it could easily become a problem later. The definition of f given at (F1) relies on n not having any definition at the time that f is used. The solution to this is to make n local to f. This is a concept that applies to almost all computer languages, whether or not they're symbolic. Change the definition (F1) to

f:= proc(t)
local n;
    a/2 + sum(A(n)*cos(w*n*t), n= 1..100) + sum(B(n)*sin(w*n*t), n = 1..100)
end proc;

If you use 1D input (aka Maple Input or Maple Notation), the above can be abbreviated to

f:= t-> local n; a/2 + sum(A(n)*cos(w*n*t), n= 1..100) + sum(B(n)*sin(w*n*t), n = 1..100);

When this is done, the n inside f will not be affected by any change made to any n outside of f. Indeed, it becomes a completely different variable that just happens to have the same name. This need for local does not occur elsewhere in your code because variables that appear on the left side of an arrow -> are automatically local in a sense (technically, they're called parameters, which is a slightly different concept than local).

[*1] There are other situations, however, where redefining a symbol is the best thing to do to maintain the human readability of the code.

[*2] The best way to change the order of evaluation in this case is a command called unapply. After you've digested the rest of material in this Answer, you should read its help page ?unapply.​​​​​​

First 69 70 71 72 73 74 75 Last Page 71 of 396