Joe Riel

9530 Reputation

23 Badges

20 years, 24 days

MaplePrimes Activity


These are answers submitted by Joe Riel

Note that the symbol e is not assigned in Maple.  As Carl does, use the function exp for the exponential function.

You can create, say, 25/100, as a Maple rational, without using symbols or the empty function, however, because the resulting expression is nonstandard (created via hacking Maple's internal format), there is no guarantee that Maple will correctly process it. Here is how it can be done.

f := (i::integer,j::integer) -> sscanf(sprintf("#%m%m",i,j),"%m")[]:

f(25,100);
                      25/100

%*2;
                       25/50

%/5;
                        5/50

f(0,0);
                         0/0

%+1;
                          0

There is a way to partially do what you want, without using subs.  The parameter modifier depends can be used here.

F := proc(m :: `module`)
   ( x :: depends('Vector'(m:-dim))) -> something;
end proc:

M := module() export dim := 2; end module:
fm := F(M);
                  fm := (x::depends('Vector'(M:-dim))) -> something

fm(<a,b>);
                  something

fm(<a,b,c>);
                  error, invalid input, fm expects ... 

 

Note that the declaration depends on the value of M:-dim at the time of execution, so

M:-dim := 4:
fm(<a,b>);
                error, invalid input, fm expects ...
fm(<a,b,c,d>);
                something

If you really want the M:-dim evaluated at the time the procedure is created, you could use unapply, however, that might not be practical with your real procedure.  Here it can be done as

unapply(something, x :: 'Vector'(M:-dim));
                                 (x :: Vector(4)) -> something

 

The usual way to do this is slightly nasty looking.

 

F := proc(m :: `module`)
  subs('_d' = m:-dim, (x::Vector(_d)) -> something);
end proc:

 If you are using a recent version of Maple, you might consider using objects rather than modules for M. 

Here's an implementation using a custom iterator.  A Maple iterator is implemented with an object that exports the ModuleIterator procedure.  That procedure returns two procedures: a predicate, hasnext, that returns true/false depending whether the iteration should continue, and a procedure, getnext, that returns the next value.  In this implementation hasnext does all the work; getnext just returns the Array that is reused for each iteration.

RoundRobin := module()
option object;
local number := 5;
export
    ModuleCopy :: static := proc( self :: RoundRobin
                                  , proto :: RoundRobin
                                  , { number :: posint := proto:-number }
                                  , $
                                )
        if number < 3 then error "must have at least 3 competitors"; end if;
        self:-number := number;
        self;
    end proc;
    
export
    ModuleIterator :: static := proc( self :: RoundRobin )
    local A,n,hasnext,getnext,first,is_odd;
        if self:-number :: odd then
            n := self:-number+1;
            is_odd := true;
        else
            n := self:-number;
            is_odd := false;
        end if;
        
        A := Array(1..n, i->i, 'datatype'=integer[4]);
        if is_odd then A[n] := 0; end if;
        first := true;
        getnext := proc()
            A;
        end proc;
        hasnext := proc()
            if first then
                first := false;
                return true;
            else
                A[..] := A[[1,4,2,seq('(i+3,i)',i=3..n-3,2),n-1]];
                return evalb(A[2] <> 2);
            end if;
        end proc;
        (hasnext,getnext);
    end proc;
    
end module:

# Example of usage

PrintPairings := proc(n :: posint)
local m,RR,rr,rnd;    
    RR := Object(RoundRobin, number=n):
    rnd := 1;
    for rr in RR do
        printf("Round %d:\n", rnd);
        for m to n by 2 do
            if rr[m]=0 then
                printf("  %d sits out\n", rr[m+1]);
                next;
            elif rr[m+1]=0 then
                printf("  %d sits out\n", rr[m]);
                next;
            else
                printf("  %d vs %d\n", rr[m],rr[m+1]);
            end if;
        end do;
        rnd := rnd+1;
    end do:
    NULL;
end proc:

PrintPairings(7):
Round 1:
  1 vs 2
  3 vs 4
  5 vs 6
  7 sits out
Round 2:
  1 vs 4
  2 vs 6
  3 sits out
  5 vs 7
Round 3:
  1 vs 6
  4 sits out
  2 vs 7
  3 vs 5
Round 4:
  1 sits out
  6 vs 7
  4 vs 5
  2 vs 3
Round 5:
  1 vs 7
  5 sits out
  6 vs 3
  4 vs 2
Round 6:
  1 vs 5
  7 vs 3
  2 sits out
  6 vs 4
Round 7:
  1 vs 3
  5 vs 2
  7 vs 4
  6 sits out


Use the symbol `&delta;x`.  To ease the typing you might assign it to dx, or alias it to dx, say via alias(`&delta;x`=dx). So you could do

alias(`&delta;x`=dx, `&Delta;x`=Dx):

and then type dx and Dx to display the two forms of interest.

Purists might object to the italicized Delta.  You could use the more complicated form `#mrow(mo("&Delta;"),mi("x"))`.  Using mo, the MathML math-operator form, is a hack; it makes more sense to use mi("&Delta;",fontstyle="normal"); alas, Maple's 2D formatter sets that as italic.

You can use the following technique to convert a fancy Math expression to a Maple symbol. In a 2D Math region, use the palettes to create the symbol you want.  Select it, right-click, and from the context-senstive menu, select 2D Math --> convert to --> Atomic Identifier.  Again select the symbol, but this time pick 2D Math --> Convert to --> 1D Math Input.  The result should be a symbol, in 1D Maple input, that displays as the typeset symbol of interest.

As Markiyan notes, an identity map is an endomorphism.  While not answering your question, note that endomorphism is an adjective, that is, it describes a property of some maps.  An identity map specifies a particular map (given the domain).

map[3](applyop,f,1,[[1,2,3],[4,5,6],[7,8,9]]);

If you don't need the minimum result, a much faster approach, applicable for the 4x4 problem, is to find the best solution for 8x2, then split each of those into 4x2.  Using the compiled version of Var with MinVal, above, I got a result in about 2 seconds, compared to 48 seconds for the minimum result. 

Be aware that the original problem, in just the two-set version, is NP-complete.

Here's an approach, using a modification of Carl's method, with a compiled procedure used to compute the minimal value. It runs in 48 seconds (Carl's took over 500 seconds on my machine).

Note: This code has been replaced one time, found a bug in previous version.

MinVal := proc(p :: Array(datatype=integer[4])
               , A :: Array(datatype=float[8])
               , lg :: Array(datatype=float[8])
               , pmin :: Array(datatype=integer[4])
               , m :: float
               , K :: float
               , n :: posint
               , num :: posint
              )
local i,j,v;
    # Initialize A, which is used as a scratchpad
    for j to num do
        A[j] := -K;
    end do;

    for i to n do
        j := p[i]+1;
        A[j] := A[j] + lg[i];
    end do;

    v := 0.0;
    for j to num do
        v := v + abs(A[j]);
    end do;

    # test for minimum
    if m <= v then
        v := m;
    else
        # update pmin
        for i to n do
            pmin[i] := p[i];
        end do;
    end if;
    return v;
end proc:


Var := proc(L::list(positive)
            , len :: posint
            , num :: posint
           )
local A, M, P, T, i, K, lg, n, p, pmin;
    n := numelems(L);
    if len*num <> n then
        error "invalid partition specification";
    end if;

    # allocate arrays used by MinVal
    A := Array(1..num, 'datatype'=float[8]);
    pmin := Array(1..n, 'datatype'=integer[4]);

    lg := Array(evalf(ln~(L)),'datatype'=float[8]);
    K := add(i, i=lg)/num;
    M := K*len;

    P := Iterator:-SetPartitions(n,[[len,num]]);

    for p in P do
        M := MinVal(p, A, lg, pmin, M, K, n, num);
    end do;

    # Convert pmin to a list of sets of indices into p
    T := ListTools:-Classify(i->pmin[i],[seq(1..n)]);
    return [seq(T[i],i=0..num-1)], exp(M);

end proc:


L := [1829.0, 1644.0, 1594.0, 1576.0, 1520.0, 1477.0, 1477.00, 1404.0
      , 1392.0, 1325.0, 1313.0, 1297.0, 1292.0, 1277.0, 1249.0, 1236.0]:

MinVal := Compiler:-Compile(MinVal):
CodeTools:-Usage((Var)(L, 4, 4));
memory used=2.39GiB, alloc change=0 bytes, cpu time=47.79s, real time=47.91s, gc time=1.94s
  [{1, 9, 13, 15}, {2, 4, 14, 16}, {3, 6, 10, 11}, {5, 7, 8, 12}], 1.006534690



An alternative technique is to use TopologicalSort to find a consistent ordering:

 

L := [map(`[]`@op,s)[]]:
TopologicalSort(L);
          [E,Z,F,P,A]

 Use ListTools:-Reverse to get the result sorted greatest to smallest.

Try ListTools:-PartialSums

It's not clear what you want.  Neither subs command makes much sense.  With the inplace option, you are substituting a matrix (CC) for theta, which appears in cos(theta).  The result doesn't make sense to Maple, it is the cosine of a Matrix.

Assign the following procedure, call it at the start of the worksheet, then execute the worksheet

SleepUntil := proc(tim::string, fmt :: string := "%D %T")
local delay,t0,t1;
uses %ST = StringTools;
    t1 := %ST:-ParseTime(fmt,tim);
    t0 := %ST:-ParseTime(fmt,%ST:-FormatTime(fmt));

    delay := ( t1:-second - t0:-second
               + 60*(t1:-minute - t0:-minute
                     + 60*(t1:-hour - t0:-hour
                           + 24*(t1:-yearDay - t0:-yearDay
                                 + 365*(t1:-year - t0:-year)))));
    Threads:-Sleep(delay);
end proc:

(SleepUntil)("12/25/13 11:58:00");

 

Combine the deqs and initial conditions into a single list or set, rather than a list of two sublists. It works fine then.

First 29 30 31 32 33 34 35 Last Page 31 of 114