Joe Riel

9660 Reputation

23 Badges

20 years, 21 days

MaplePrimes Activity


These are replies submitted by Joe Riel

Here's a slightly modified approach.  It requires the same two files as before, however, when automw.mpl launches xmaple, it uses two -c options to assign serverfcn and then start the Socket server.   The first time automw is run, it opens the desired worksheet and launches the port server.  Subsequent calls open worksheets in new tabs.

#!/bin/bash
#~/bin/automw
 
# This is the shell script which starts the worksheet
# autoloader client (commandline maple file automw.mpl)
 
# The variable fname is assigned the full path of the
# first arg of this shell script. 
# The commandline maple script can grab that.

fname="$1"
# convert fname to absolute path
if [ ${fname:0:1} != "/" ]; then
    fname=`pwd`/$fname;
fi
export fname
maple -s -q $HOME/bin/automw.mpl &
Here is the modified automw.mpl  

# ~/bin/automw.mpl
# This runs a single procedure with no arguments.
# That procedure gets a worksheet filename from the
# shell variable "fname".
# It then attempts to open a Socket on port 2525 and,
# if successful, sends a command to open the file
# as a worksheet.
# If unsuccessful, it launches xmaple, opens the worksheet,
# and starts the server so that subsequent calls to
# automw open worksheets in tabs.

module()
local fn, str, sid, serverfcn;

    serverfcn := proc(sid)
    local str;
        str:=Sockets:-Read(sid);
        print(parse(str));
        NULL;
    end proc;

    fn := getenv("fname");

    try
        sid := Sockets:-Open("clifford",2525);
        Sockets:-Write(sid, sprintf("INTERFACE_WORKSHEET(display,file=\"%s\")",fn ));
    catch "cannot establish TCP connection":
        system(sprintf("maple -x "
                       "-c'Sockets:-Serve(2525,%a);'"
                       " %s &"
                       , eval(serverfcn)
                       , fn
                      ));
    end try;
end module:


 

Yes, I've always found that a big strange. The same occurs with _npassed:

proc() _npassed end proc;
                                           proc() nargs end proc

I modified the automw script to convert a relative path for the argument to a full path, that allows running automw from any directory.  Is there a nicer way to do the conversion?  The following seems quite the (bash) hack:

fname="`cd ${1%/*};pwd`/${1##*/}"
export fname
maple -s -q $HOME/bin/automw.mpl &

A modest improvement to your first suggestion is to merge the two calls to op by using a list as the first argument:

 op([1,1], e1);

Because e1[1] has but one operand, you can also do

 op([1,..], e1);

 

A modest improvement to your first suggestion is to merge the two calls to op by using a list as the first argument:

 op([1,1], e1);

Because e1[1] has but one operand, you can also do

 op([1,..], e1);

 

I see now.  Presumably the help page is using the more general sense of type rather than the Maple type.

I'm not sure what confuses you.  It is saying that you can replace the first item in the sequence used to assemble an object with its symbolic dagtag.  For example:

tmp := disassemble(addressof(3*x));
                                    tmp := 16, 136157948, 7
pointto(assemble(SUM, tmp[2..]));
                                             3*x

If you know how dagtags work, you should be able to guess what the following returns

pointto(assemble(PROD, tmp[2..]));

 

It isn't hard to figure out what the conversion is, though not all dagtags can be represented as a normal Maple object.  To print the dagtags, do

for i do try lprint(kernelopts(dagtag=i)); catch: break; end try; end do:

Note that the type that matches an expression doesn't necessarily match the dagtag. For example,

type(3*a, `+`);
                                 false
type(3*a, `*`);
                                 true
dismantle(3*a);
SUM(3)
   NAME(4): a
   INTPOS(2): 3

 

Another method is to use subsop to eliminate the last element of each sublist:

L3 := map2(subsop, -1=NULL, L2);

Also, here's another method, possibly somewhat obscure, for doing the tally.

frontend(Statistics:-Tally, [L3], [{listlist},{}]);

Here's an amusing way to tally; the tally is the exponent of each sublist:

L := [[a, b], [a, b], [b, a], [a, a]]:
`*`(L[]);
                                                2
                                          [a, b]  [b, a] [a, a]
Not particularly practical...

Another method is to use subsop to eliminate the last element of each sublist:

L3 := map2(subsop, -1=NULL, L2);

Also, here's another method, possibly somewhat obscure, for doing the tally.

frontend(Statistics:-Tally, [L3], [{listlist},{}]);

Here's an amusing way to tally; the tally is the exponent of each sublist:

L := [[a, b], [a, b], [b, a], [a, a]]:
`*`(L[]);
                                                2
                                          [a, b]  [b, a] [a, a]
Not particularly practical...

Another issue with using the short-form of use (or uses) is that code will break if an export is added to the used module that clashes with one of your local variables (it won't actually break until you rebuild, that is, reevaluate the code).  For that reason, I only use the short form when writing throwaway code.  For production work I either assign a shortname using an equation for each export that is used, or assign a shortname for used module and then use that in the code.  For example

myproc := proc()
uses LA=LinearAlgebra;
   LA:-MatrixMultiply(...);
end proc:

Doug's solution, using selectremove, is the proper approach. I'm responding mainly to point out the reason that your approach is so slow.  It isn't so much because it uses a do loop, but rather because you are building up a sequence (two sequences) term by term in the loop.  That is, as the loop progresses, R becomes

R1
R1,R2
R1,R2,R3
R1,R2,R3,R4,...

Each new sequence must be created and stored.  For a final sequence of n terms, this is O(n^2) in time and memory usage.   The standard method for avoiding this is to add the terms to a table and then, when complete, convert the table to a list.  For example

R := table(): L := table():
j := 0: k := 0:
for i to Sall do
   if S[i][2] <= cutoff then
       j := j+1;
       R[j] := S[i];
   else
      k := k + 1;
      L[k] := S[i];
   end if;
end do:
R := convert(R, list);
L := convert(L, list);

Of course, using selectremove is the better approach here...

That will, indeed, work. As you suspect, it is not the fastest.  The principal reason that it is slow is that every comparison, and there are typically n*log(n) of them, requires a call to the user procedure (x,y) -> evalb(x[i]<y[i]).

The searching-with-attributes that I mentioned above avoids that by first extracting the key from the list than using the builtin sort, which doesn't require an external comparator.  The trick is that the computed key for each row (the value in the selected position) is tagged (attributed) with the entire row.  After sorting the keys we merely extract the attributes.

SortLL := proc(LL::listlist(numeric), pos::posint)
local L;
    map(attributes, sort([seq(setattribute(SFloat(L[pos]), L), L = LL)]))
end proc:
foo := [[-50001, 1], [61, -99], [303, 4]]:
SortLL(foo,1);
                      [[-50001, 1], [61, -99], [303, 4]]

SortLL(foo,2);
                      [[61, -99], [-50001, 1], [303, 4]]
 

Conceptually a better way to do this is to use an inplace-sort on an Array of floats; that can be accomplished with external compiled routines and should be quite a bit faster.  I'm looking into doing that.

I'm not sure how you want to sort the list of lists of floats.  Could you give an example?

Sorting a list of lists using a particular element as the key is easy. To make it fast use sorting with attributes. Here is how you can do that with your given example,

foo := [[-50001, 1], [61, -99], [303, 4]]:
map(attributes,sort([seq(setattribute(SFloat(L[2]),L), L = foo)]));
                                         [[61, -99], [-50001, 1], [303, 4]]

I don't quite understand what you want.  In the code I gave, vars is computed from R.  In what sense must it be of indefinite length? 

Is the following of use (not directly, but maybe it will give you a clue as to how to do what you really want, efficiently)?

AllVars := proc(i,j,k,l)
local ii,jj,kk,ll;
global c;
    {NULL
     , seq(seq(c[0,jj,0,ll], jj=0..j+1), ll=0..l)
     , seq(seq(c[ii,0,kk,0], ii=0..i+1), kk=0..k)
    };
end proc:
Presumably you have some way of combining them to generate the linear combinations...
First 132 133 134 135 136 137 138 Last Page 134 of 195