Carl Love

Carl Love

28055 Reputation

25 Badges

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

MaplePrimes Activity


These are answers submitted by Carl Love

The trouble with your method is that you repeatedly add elements to existing lists or sets. Unfortunately, that operation is very inefficient in Maple. It is so natural to approach this problem recursively; however, I can't think of any way to efficiently do it recursively in Maple, even after thinking about it for hours.

Here is a way to do it using seq. This method is faster than Iterator. (In fairness, I must say that I learned this technique from a post by Joe Riel where he applied it to Cartesian products.) I also show a better way to do your indexing procedure TkSubSetList. And I also compare with VV's recursive method.

A better way of listing combinations

Carl Love 2016-Oct-10


restart:

 

Observe how the three nested loops below produce all size 3 sublists of [1..5].

 


n:= 5:
S:= [seq(seq(seq([k,j,i], i= j+1..n), j= k+1..n), k= 1..n)];

[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]

 

So what we need to do is build an arbitrarily deeply nested seq statement.


nkSubsetL:= proc(n::nonnegint, k::nonnegint)
description "Returns a list of all sublists of [1..n] of size k.";
local Seq,i,j;
     if k > n then return [] end if;
     if n*k=0 then return [[]] end if;
     [eval](
          subs(
               Seq= seq,
               foldl(
                    Seq,
                    [seq(i[j], j= k..1, -1)], #the k-tuple
                    seq(i[j]= i[j+1]+1..n, j= 1..k-1), i[k]= 1..n
               )
          )
     )
end proc:


nkSubsetL(5,3);

[[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]


#VV's recursive method
rcomb:= proc(n, k, p:= [])
     if k=n then return [seq(1..n),op(p)] fi;
     if k=1 then return seq([i,op(p)],i=1..n) fi;
     rcomb(n-1,k,p),rcomb(n-1,k-1,[n,op(p)])
end:


rcomb(5,3);

[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 5], [1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5], [3, 4, 5]


#VV's method, modified by Carl
rcomb2:= proc(n::nonnegint, k::nonnegint)
local i;
     if k > n then ()
     elif k=0 then []
     else
          proc(n,k,p:= [])
               if k=n then [seq(1..n), p[]]
               elif k=1 then seq([i,p[]], i= 1..n)
               else thisproc(n-1, k, p), thisproc(n-1, k-1, [n,p[]])
               fi
          end proc(n,k)
     fi
end proc:
     


rcomb2(5,3);

[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 5], [1, 3, 5], [2, 3, 5], [1, 4, 5], [2, 4, 5], [3, 4, 5]

 

Below are procedures that use the seq method to form combinations from arbitrary sets/lists.


#Returns a list of all k-sublists or k-subsets of an arbitrary set or list.
TkSubsetL:= (T::{set,list}, k::nonnegint)-> map2(`?[]`, T, `[]`~(nkSubsetL(nops(T), k))):

#An abbreviation of the original TkSubSetList.
TkSubSetList:= (T,k)-> map(A-> map(i-> T[i], A), nkSubsetL(nops(T), k)):


TkSubsetL({a,b,c,d,e}, 3);

[{a, b, c}, {a, b, d}, {a, b, e}, {a, c, d}, {a, c, e}, {a, d, e}, {b, c, d}, {b, c, e}, {b, d, e}, {c, d, e}]


TkSubSetList({a,b,c,d,e}, 3);

[[a, b, c], [a, b, d], [a, b, e], [a, c, d], [a, c, e], [a, d, e], [b, c, d], [b, c, e], [b, d, e], [c, d, e]]

 

Time tests:


(n,k):= (22,11):

#Old Maple recursive method:
gc(); S0:= CodeTools:-Usage(combinat:-choose(n,k)):

memory used=2.88GiB, alloc change=469.49MiB, cpu time=39.61s, real time=26.95s, gc time=19.05s

#Carl's non-recursive seq method:
gc(); S1:= CodeTools:-Usage(nkSubsetL(n,k)):

memory used=199.10MiB, alloc change=9.48MiB, cpu time=4.44s, real time=2.87s, gc time=2.08s

#New Maple non-recursive method:
gc(); S2:= CodeTools:-Usage([seq([seq(x, x= c+1)], c= Iterator:-Combination(n,k))]):

memory used=339.59MiB, alloc change=5.62MiB, cpu time=6.12s, real time=4.89s, gc time=1.59s

S2:= [{S2[]}[]]: #Compensate for the unusual order used by Iterator.

#VV's recursive method:
gc(); S3:= CodeTools:-Usage([rcomb(n,k)]):

memory used=374.76MiB, alloc change=13.46MiB, cpu time=4.50s, real time=2.92s, gc time=2.08s

S3:= [{S3[]}[]]: #Compensate for the unusual order.

#VV's recursive method, modified by Carl
gc(); S4:= CodeTools:-Usage([rcomb2(n,k)]):

memory used=337.09MiB, alloc change=13.46MiB, cpu time=4.53s, real time=2.73s, gc time=2.28s

S4:= [{S4[]}[]]:

 

These next two are indexing methods. Their times are to be compared with each other, but not with the above.

 

#Carl's indexing method, based on his seq method.
gc(); S5:= CodeTools:-Usage(TkSubsetL([$1..n], k)):

memory used=387.47MiB, alloc change=52.25MiB, cpu time=9.23s, real time=5.05s, gc time=5.08s

#The OP's indexing method, based on Carl's seq method.
gc(); S6:= CodeTools:-Usage(TkSubSetList([$1..n], k)):

memory used=0.86GiB, alloc change=14.87MiB, cpu time=13.97s, real time=8.93s, gc time=6.25s

#Verify that all results are the same.
evalb~([seq(S0=S||i, i= 1..6)]);

[true, true, true, true, true, true]

 


Download AllCombinations.mw

Indices, which are formed with square brackets, and different from subscripts, which are formed with double underscore. The two forms display pretty much the same in the GUI. However, a subscript is an integral part of the name to which it is attached, and hence it can't be substituted for an integer or anything else. A subscript is intended for display purposes, not programmatic purposes.

Additionally, you'll achieve better results with mul rather than product (lowercase p). Here's your worksheet, modified:

restart:

with(Statistics):

N := 2:
X__E__n:= RandomVariable(Normal(mu__E__n, sigma__E__n));
for n from 1 to N do
   X__E[n] := RandomVariable(Normal(mu__E[n], sigma__E[n]));
end do:

_R

#n := 'n':

PDF(X__E__n, x__E__n);  # but this one suits me
                            # compared to the first coding the desired abd undesired outputs
                            # are permuted. What is th reason for this ?

(1/2)*2^(1/2)*exp(-(1/2)*(x__E__n-mu__E__n)^2/sigma__E__n^2)/(Pi^(1/2)*sigma__E__n)

# For PDF(X__E__n, x__E__n) suits me, I fix n to 1 :

PDF(X__E[1], x__E[1]);

# Why do I not receive the previous output where n is simply replaced by 1 ?

(1/2)*2^(1/2)*exp(-(1/2)*(x__E[1]-mu__E[1])^2/sigma__E[1]^2)/(Pi^(1/2)*sigma__E[1])

# At the very end I would like to obtain the likelihood of a sample (x__E__1, x__E__2)
#
# PS : I know there exists a function "Likelihood" in the Statistics package but, for
#      some reasons, I do not want to use it.

# At a first stage, for pedagogical reason, I want to display this likelihood in
# a compact formal expression
n := 'n':
Product(PDF(X__E__n, x__E__n), n=1..'N');   # This is exactly what I want

Product((1/2)*2^(1/2)*exp(-(1/2)*(x__E__n-mu__E__n)^2/sigma__E__n^2)/(Pi^(1/2)*sigma__E__n), n = 1 .. N)

# Stage 2 : expansion of this likelihood

combine(mul(PDF(X__E[n], x__E[n]), n=1..N));  # does not returns the result I was expecting for
                                         # ... probably "normal" but I do not understand why

(1/2)*exp(-(1/2)*(x__E[1]-mu__E[1])^2/sigma__E[1]^2-(1/2)*(x__E[2]-mu__E[2])^2/sigma__E[2]^2)/(Pi*sigma__E[1]*sigma__E[2])

 


Download WhatHappensHere.mw

Here's a much-simplified version of your code:

funcs := [x, 3*x, x^2, 5*x];
for i to nops(funcs) do listM[i] := diff(funcs, [x $ (i-1)]) end do;
M := convert(convert(listM, list), matrix);
linalg:-det(M);

P.S. Here's a more-direct way:

M:= matrix([seq(diff(funcs, [x$(i-1)]), i= 1..nops(funcs))]);

You think that D[3](y)(L) refers to the 3rd derivative with respect to the first variable. That's incorrect: Rather, it refers to the 1st derivative with respect to the 3rd variable (regardless of the fact that y is a univariate function). There are several ways to represent the 3rd derivative with respect to the first (and only) variable:

(D@@3)(y)(L)
D[1,1,1](y)(L)
D[1$3](y)(L)

Likewise for the 2nd or any other order of derivative.

You need to spell out Heaviside and use exp(...) instead of e^.... The command is

inttrans:-laplace(Heaviside(t-1)*exp(3*t-3), t, s);

The Wronskian command is predefined. See ?Wronskian.

The linalg package has long been deprecated. It's functionality has been replaced by the packages VectorCalculus and LinearAlgebra.

The internal reference to h must be stored as z5:-h because h is in z5, so it needs to know where to look up h on re-evaluation of the expression. But you don't need to see the z5:- if you use a `print/h` procedure. Change z5 to this:

z5:= module()
option package;
export
     h:= F-> expand(evalindets(D(F)/F, specfunc(D), d-> op(d)*'h'(op(d))))
;
local
     ModuleLoad:= proc() :-`print/h`:= ()-> ':-h'(args) end proc,
     ModuleUnload:= ()-> unassign(':-`print/h`')
;
     ModuleLoad();
end module:

Of course, you can include any other locals or exports that you want in the module.

The key thing is that you can get any function f to prettyprint differently by defining a global procedure `print/f`. Since the procedure needs to be global, it needs to be assigned in a ModuleLoad procedure.

Symbolic antiderivatives in Maple are allowed to be discontinuous. This especially happens with complex functions. You can see this discontinuity in this plot (the red line is the real part):

F:= I*arctan(sqrt(exp(2*I*t)-1))-I*sqrt(exp(2*I*t)-1):
plot(([Re,Im])~(F), t= 0..Pi, discont);

The int command correctly adjusts for the discontinuity when it's a definite integral.

In the line that defines vNN, you have

vNN= ....

That needs to be

vNN:= ....

In the next line, use eval instead of algsubs:

pressure:= eval(nMom, vNN);

Do you mean something like this?

restart:

interface(rtablesize= 30):

Matrix((30,2), (i,j)-> `if`(j=1, i, 2^i));

Matrix([[1, 2], [2, 4], [3, 8], [4, 16], [5, 32], [6, 64], [7, 128], [8, 256], [9, 512], [10, 1024], [11, 2048], [12, 4096], [13, 8192], [14, 16384], [15, 32768], [16, 65536], [17, 131072], [18, 262144], [19, 524288], [20, 1048576], [21, 2097152], [22, 4194304], [23, 8388608], [24, 16777216], [25, 33554432], [26, 67108864], [27, 134217728], [28, 268435456], [29, 536870912], [30, 1073741824]])

 


Download Powers_of_2.mw

The variable cape very likely has an unassigned variable in it, so it can't be evaluated to a number. If you give the command print(cape), you'll very likely see what that unassigned variable is. If cape is too long to find that variable, the command indets(cape, name) will help you find it.

If you need further help, please use the green up arrow on the toolbar in the MaplePrimes editor to upload your worksheet. It's very difficult to make an accurate diagnosis based on simply reading the code "by eye".

I see what you're trying to do. It's a very common model for iterative numerical algorithms: You want to limit the number of iterations so that you don't have an infinite loop if the method is not converging. You need to use a for-while-do loop.

restart:

PointFixe:= proc(g, d, a, N)
local o, i, u, pm, relerr;
     pm:= 0.222e-15;
     u:= d;
     relerr:= a;
     for i to N while relerr >= a do
          o:= u;
          u:= evalf(eval(g, x= u)); #eval, not subs
          relerr:= abs((u-o)/(abs(u)+pm));
     od;
     #Check if loop ended due to iteration count rather than convergence.
     if i = N+1 then
          error "Relative error is %1 after %2 iterations.", relerr, N
     end if;
     userinfo(1, PointFixe, "Used", i, "iterations.");
     u
end proc:       

 

infolevel[PointFixe]:= 1: #Activates the userinfo statement.

PointFixe(exp(x)-x-5, 2, 1e-8, 100);

Error, (in PointFixe) Relative error is 0.159964237326880e-3 after 100 iterations.


PointFixe(exp(x)-x-5, 2, 1e-8, 1000);

PointFixe: Used 210 iterations.

-2.45716106995070

 

 

Download PointFixe.mw

Note that the given answer is not correct. The algorithm converged because the step size got too small. So, you'll need to add a check for that. You should have abs(u) being close to 0 to return without error.

You need more square brackets in the plot commands to indicate a parametric plot:

InertiaAxis1 := t->plot([x, V1(t)[2]*x/V1(t)[1], x = -2 .. 2]);
InertiaAxis2 := t->plot([x, V2(t)[2]*x/V2(t)[1], x = -2 .. 2]);

There's a command specifically for this equation. See ?LinearAlgebra,LyapunovSolve.

Here's a one-line procedure that tests whether your lists are valid:

valid:= (L::list(algebraic), V::list(name))->

     not `or`(seq(type(L[k], freeof({V[]} minus {V[k]})), k= 1..nops(V)))
:

See ?type,freeof.

You mentioned monomials. This Question is about polynomials, not monomials.

First 208 209 210 211 212 213 214 Last Page 210 of 395