Paul

485 Reputation

8 Badges

14 years, 87 days
Paul DeMarco is the Director of Development at Maplesoft, a position that has him involved with technical planning and development of Maple and the various core technologies that use Maple as a computation engine. He joined Maplesoft in September 1996 while studying at the University of Waterloo in the CS/EEE program -- a track that combines core math and computer science courses with electrical engineering electives. Paul's development work in the Math and Kernel Groups over the years touches a wide variety of areas, including algorithms, data structures, and connectivity with other products. He is also involved with core Maple as well as Maple T.A.

MaplePrimes Activity


These are answers submitted by Paul

 

define_external can be called in two different ways:  (1) specify all of the argument types and let Maple handle the conversion mapping, or (2) tell it that you will handle the conversions on your own.

For this example using function pointers, you will want to use method (2).  This is documented in ?define_external,CustomWrapper (http://www.maplesoft.com/support/help/Maple/view.aspx?path=define_external/CustomWrapper).  

In a nutshell, replace all of the argument type declarations in the define_external calling sequence with the keyword MAPLE.  Then, create a .dll with an entry point that looks like this:

    

#include "maplec.h"
ALGEB  rk4( MKernelVector kv, ALGEB fn_args );

 

In the C code you will need to look through "fn_args"  and pick out the arguments you want before calling your rk4vec procedure directly.

 

You will need to use strings to enter big integers into Maple, and to go back and forth between OpenMaple and Java's BigInteger class.

Somehing like the following should work:

Algebraic a1 = engine.evaluate("39614081257132168796771975168;");
String s = a1.toString();
BigInteger(s);

Here is an approach that uses a separate thread to gather the messages in each grid node.  The thread blocks when calling Grid:-Receive until a message is ready.  When the message comes through, it puts the message in a table.  At the same time, the "worker" procedure can call Messages:-NonBlockingReceive, which will look in the table to see if there is any saved data.  If so, return it, otherwise just return NULL without waiting. 

There are some tricky details when the job is complete.  Here we have all of the senders create a special "done" message so that the receiver threads can shut down.  There is also an important detail about locking around access to the "data" table.  In order to safely unassign the message that has been received, you need to lock around both the assign and unassign statements.

Here is the code, it makes liberal use of printf statements so that you can see what is going on when it is run.  The first part is a "Messages" module that implements the receiver thread, and the NonBlockingReceive procedure.  The second part is a "work" procedure that just loops a bit while sending and receiving messages.  The two commands at the bottom initialize the grid nodes and start the job.

Messages := module()
    local data, dataAccessLock, first, last;

    export Init := proc()
        data := table():
        dataAccessLock := Threads:-Mutex:-Create();;
        first := 0;
        last := 0;
    end proc;

    export NonBlockingReceive := proc()
        local r;
        if first = last then
            r := NULL;
        else
            r := data[first];
            Threads:-Mutex:-Lock(dataAccessLock);
            unassign('data[first]');
            Threads:-Mutex:-Unlock(dataAccessLock);
            first := first+1;
        end if;
        r;
    end proc:

    export ReceiveThread := proc(me)
        local msg;

        printf("Thread started %d\n",me);
        while true do
            msg := Grid:-Receive();
            printf("Node %d stashing message data[%d] = %a\n",me,last,msg);
            if msg = "done" then
                break;
            end if;
            Threads:-Mutex:-Lock(dataAccessLock);
            data[last] := msg;
            Threads:-Mutex:-Unlock(dataAccessLock);
            last := last+1;
        od;
        printf("Thread finished %d\n",me);
        0;
    end;
end module:

work := proc()
    local me := Grid:-MyNode();
    local NN := Grid:-NumNodes();
    local msg, i, id, total := 0;;
    printf("I'm node %d\n",me);

    Messages:-Init();
    id := Threads:-Create(Messages:-ReceiveThread(me));

    # simulate a loop that interleaves work with send & receive
    printf("Node %d starting work loop\n",me);
    for i from 1 to 300 do
       msg := Messages:-NonBlockingReceive();
       if msg <> NULL then
           printf("Node %d got %a\n",me,msg);
           total := total + msg;
       else
           printf(".");
       end if;
       if i mod 100 = 0 then
           printf("Node %d sending message to node %d\n",me,(me+1) mod NN );
           Grid:-Send( (me+1) mod NN, i);
       end if;
    od;
    Grid:-Send( (me+1) mod NN, "done");

    # done generating work; gather up the remaining messages
    Threads:-Wait(id);  #this will wait until the last message is delivered
    while true do
       msg := Messages:-NonBlockingReceive();
       if msg <> NULL then
           printf("Node %d got %a\n",me,msg);
           total := total + msg;
       else
           break;
       end if;
    od;
    printf("Node %d finished\n",me);

    total;
end;

Grid:-Set(work,Messages);
Grid:-Run(work);

 

 

Indeed the problem is a bug when resizing an Array with a datatype that doesn't include zero.  Because type(0,string) fails, Maple needs to choose a different initial value other than zero to fill in the resized memory block with.  The defect lies in the way it tries to pick the 'fill' value.

The workaround as mentioned in an earlier post is to use datatype=anything.  If you really need a string datatype, you could try datatype={string,identical(0)}. 

This will be logged and fixed. 

 

The evalM command is for calling Matlab commands from Maple.  I think Subhra is looking for the reverse direction -- calling Maple commands from within Matlab.  This can be done using the Maple Toolbox for Matlab (MTM).

When you first installed Maple it may have asked you about a path to Matlab in order to set up MTM.  If you have the directory $MATLAB/toolbox/maple (where $MATLAB is the path to your Matlab install), then you likely have everything all ready to go.  Otherwise, run "MapleToolbox.bat", or similar platform specific install script sitting in your root Maple program directory.

The documentation for this toolbox is all inside Matlab.  Reference it by typing the following at the Matlab command prompt:

>> doc maple

There are many commands to seamlessly call into maple to do computations using Matlab syntax.  There is also a general command called "maple", which will accept arbitrary Maple expressions.  For example:

>> x = sym('x');
>> x^3+cos(2*x)-1

 ans =
          3
         x   + cos(2 x) - 1
>> diff(x^3)
 
 ans =
                   2
               3 x
>> maple('int',ans,'x')
 
 ans =
                   3
                  x
>> maple('evalf(Pi,10)')

 ans =
            3.141592654
  
 

The commands above are all typed at a Matlab prompt.  sym declares a variable as a Maple expression, which you can then use with various commands like "diff", that are part of MTM (and call directly through to Maple's diff command).  The first use of the maple command shows how to pass arguments computed in Matlab.  The second use shows a self contained Maple expression.

Automatic Maple-type to Fortran-type conversion is only set up for the core types described in ?define_external/types.  More complicated compound types like arrays of strings require a wrapper layer with hand translations using Maple's external API to pick apart the Maple types. 

If you are adventurous you can try writing the wrapper in C using the Watcom compiler to interface to your Fortran .dll.

 

To restate your question with a simple example, consider the following:

> p := proc(a) option remember; A[1]+A[2]; end:
> A := Array([1,2]):
> p(A);
                                           3

> A[2] := 5:
> p(A);
                                           3
 

The remember table is being used to fetch the result in the second case because it is seeing exactly the same arguments passed into the procedure call.  There has been some discussion at Maplesoft to change the behaviour of remember tables such that they are bypassed when mutable argument is given.  In these cases the procedure cannot really tell if it should returned the cached value or not.   The current behaviour assumes that the given array has not changed since the last call.  This is useful in many situations, but potentially dangerous.

For your example it is not clear that remember tables would help.  Your code can be modified to manually do a remember-like lookup without option remember:

Rook := proc (A, m, n, B, k, rem )
local C, i, j, h, l, count, v;

 #manual option remember
  v :=  rem[ convert(A,listlist),m,n,B,k ];
  if v::integer then
      print("using remembered value");
      return v;
  end if;

count := 0;
  if k = 1 then
    for i from 1 to m do
      for j from 1 to n do
        if `not`(`in`([i, j], B)) then
          if add(A[p, j], p = 1 .. m) = 0 then
            if add(A[i, q], q = 1 .. n) = 0 then
              count := count+1
            end if
          end if
        end if
      end do
    end do
  else
    C := Array(1..m,1..n);   #initialize as an Array so it isn't created as a table
    for i from 1 to m do
      for j from 1 to n do
        if `not`(`in`([i, j], B)) then
          if add(A[p, j], p = 1 .. m) = 0 then
            if add(A[i, q], q = 1 .. n) = 0 then
              for h from 1 to m do
                for l from 1 to n do
                  C[h, l] := A[h, l]
                end do
              end do;
              C[i, j] := 1;
              count := count+Rook(C, m, n, B, k-1,rem);
              C[i, j] := 0
            end if
          end if
        end if
      end do
    end do
  end if;
count := count/k
end proc:


A2 := Array(1 .. 20, 1 .. 20,fill=0):
B1 := {[1, 1]};

t := time();
Rook(A2, op(map(rhs,[ArrayDims(A2)])), B1, 2, table());
time() - t;
 

I tried to keep the code exactly the same, except I added a constructor call to create C as an array -- previously it was being implicitly created as a table.  This just helps a bit with the convert/listlist call in the remember lookup.  Note that the listlist conversion is expensive and uses a lot of memory.  It is necessary to illustrate this example though, as you need to keep a copy of all the elements of the array in order to do a proper remember  lookup.  I wouldn't recommend doing this in practice. 

After running the new example you may notice that ("using remembered value") is never printed.  Due to the nature of this example, it is never the case that a cached value would be fetched from the remember table.  Your original example only ran fast with option remember because it wasn't working as intended.

 

Maple TA 4.0 supports using MapleNet as the infrastructure to evaluate commands.  Using this setup you will get the GUI's plot renderer in Maple TA instead of the commandline version's. Greek characters such as &pi will render correctly.

1.      I have noticed that the time set in the assignments editor does not appear the same on the class homepage. My supplier then told me to fix a the database to GMT+1 and everything seemed consistent. However, for some reason this then started behaving oddly again, being one hour out between the two readings after behaving OK!! Why is this behaving in this way? Surely, there must be a definitive setting? (I live in the UK). Perhaps it is the calendar facility setting that is fickle?

The reason for the behavior you are seeing is that GMT+1 doesn't account for daylight saving time (DST) which gives +-1 hour jumps during the year. To make the TA time switch together with DST, the timezone in the database should be set for the UK to GMT0BST (where the "0" in the middle is zero, not letter O).  
 

2.     The ‘assignments’ page for instructors – it is very slow in loading from whichever page I try to link to it in MapleTA. It may take in excess of half a minute. It is very strange as access and links to all other pages are fine and take place within seconds if not immediately. We carried out the vacuuming recommended by the supplier but no improvement. Why this page?

Vacuuming the database is a good start.  If you are currently using  TA 3.0, make sure that you have installed all the hotfixes issued for this version -- there were some that improved performance.

3.      I have had a handful of complaints from students that, when they have clicked on ‘grade’ on finishing an assignment, then they have been logged out and returned to the login page. When they have then logged in again, there is no record of that particular attempt at the assignment. This appears to be an intermittent, randomly occurring problem in a small minority of cases. We are sending log files to MapleTA as requested. Has anyone experienced such odd behaviour. We have rebooted but to no avail.

The login page will be shown when the TA session expires.  This happens when a student is inactive in TA for more than 30 minutes (whereupon they just need to login again and can continue where they left off).  Answered questions get recorded in the database immediately after submitting the answer, so it shouldn't be possible to lose the record of a particular assignment attempt. If however the test is set up as a practice assignment (rather than a Quiz assignment), then, by design no grade and no history is recorded. 
 

4.      We are not been able to receive emails from Mapleta. This means that, any student who has gone through the ‘forgot your password?” has found the Mapleta has changed it and it has not been sent in an email. Yes, we have checked all the addresses in the database for the relevant servers

TA has to be configured to point to your mail server.  Check that the settings for the "mail" group in the system_properties database table is correct.   The "From:" address used by Maple TA must be a valid address recognized by the mail server.  Also, the mail server must be accessible by the Tomcat user from the host where Maple TA is running.
 

And, no, it is not practical to go to v4 during teaching.

Unlike the upgrade from TA 2.5 to TA 3.0, which involved major architecture changes (use of Postgres database, and Tomcat web server), the upgrade from TA 3 to TA 4 is easy and low risk, even when done in the middle of a semester.  Still, the problems you are seeing with TA 3.0 look like they can be addressed without needing an upgrade.

 

-PD

Just a quick note on workarounds for some of these issues:

(3) Right now, you will get an error when using the LaTex to .qu converter, that the Maple question type isn't known.  You can ignore that message and the .qu file will be generated properly.  The LaTeX converter is available on the maplesoft web site and isn't in the product, but the task of updating it is in the queue.

(4) Try having Maple return a list of expressions and use Maple T.A.'s switch command to get at each one. 

(6) Maple T.A. has traditionally used the graphics export engine provided by the Maple commandline interface.  This is still the default in Maple T.A. 4.0, but you now have the option of connecting to MapleNet as the back-end math and graphics engine.  MapleNet uses the more modern java-based plot drivers.  Try setting up MapleNet to get access to new plot features like gridlines and polar axes, as well as improved quality.

-PD

 



 

The online help ?OpenMaple,C,textCallBack says:

    MAPLE_TEXT_QUIT    Response to a Maple quit, done, or stop command.
 

Theoretically, this could probably show up on some other kind of controlled shutdown like an out-of-memory event.  

To try and reproduce the problem I created a simple OpenMaple app that called EvalMapleStatement to assign expr to the large expression from Tony's last post, followed by  EvalMapleStatement(kv,Logic:-BooleanSimplify(expr)):   Running in the Maple 12 beta, this finished in about 184 seconds.  I had to set my shell's stacksize limit down to 450kB before I started seeing problems, but then I just got the standard "too many levels of recursion" error, not a MAPLE_TEXT_QUIT callback.  The memory and stack required for this example are miniscule, so I doubt you're running into system limits; unless maybe the main driver of your OpenMaple application is resource heavy, and possibly doing other things at the same time in another thread.

Switching back to Maple 11 is an excercise in patience -- it's still running after 30 minutes. 

 -PD

 

I just tried the Upgrade installer of Excel 2007. I previously had a working Maple-Excel addin, but the upgrade removed it. Adding it back in was a bit different. Here are the steps: - click the MS Office Button and select "Excel Options" - click Add-ins - in the "Manage" box select "Excel Add-ins" then click "Go" - click "Browse" - navigate to the Excel subdirectory of your Maple install and select WMIMPLEX.xla (ie. select $MAPLE/Excel/WMIMPLEX.xla) Now, go back into your spreadsheet and try a formula, something like =maple("1+1"). I tried a few things and they all worked fine with Excel 2007. I was using Maple 11.01. If your Excel/Maple link didn't work after upgrading, I'd suggest removing the addon from Excel and installing it again. -PD
To protect against corruption of a repository on a multi-user system, or when multiple Maple sessions are open and writing to the same repository, Maple uses POSIX locks via the lockf() command. I don't know why there would be a lock set on your repository -- possibly there is a hung mserver process still running on your system? If necessary you can bypass repository locking by setting the environment variable DISABLELOCKING=1.
Only one OpenMaple connection is allowed per process, so you can't call StartMaple a second time in another thread. However, with Maple 11's Threads package you can start multiple threads within a shared kernel. Take a look at ?Threads -PD
The Maple help page ?Matlab,setup describes what needs to be done before a link to the MATLAB engine can be established. I've pasted this page below. Note that this statment is misleading: "If with(Matlab) returns an error, then you should follow the instructions in this document." Loading the Matlab package nolonger establishes the link to Matlab, as not all commands in this package need to call Matlab in order to compute. The first command that uses MATLAB will try to establish the link. The statement should instead say, "if Matlab[openlink]() returns an error, ...". Here are the setup instructions: Configuring a Computer for Matlab The Maple-MATLAB link works with MATLAB version 7 (R14) on most platforms that have Maple and MATLAB versions. Versions of Maple running on Macintosh, Compaq True64, SGI IRIX, and IBM-AIX use MATLAB version 6.5 (R13). To determine if the link works on a platform, use the following Maple command. `Matlab/valid_os`(); For the Maple-MATLAB link to work properly, you may have to update your configuration files. If the command with(Matlab) returns a list of function names, then your setup is correct and no additional configuration is necessary. If Matlab[openlink]() returns an error, then you should follow the instructions in this document. Since setup is platform-dependent, follow the instructions for your machine architecture. Windows 98 and ME The following instructions describe how to set the path and update the Windows Registry. These instructions assume that MATLAB is installed on the C: drive in a directory called MATLAB. Substitute the appropriate drive letter and directory name if necessary. 1. Add the following line to the end of your Autoexec.bat file to specify the correct version of MATLAB. SET PATH=%PATH%;C:\MATLAB7; 2. To restart the computer, click the Start button, then Shutdown, and then Restart. 3. Start Maple and enter the command with(Matlab). If this command returns a list of function names, then the Maple-MATLAB link is working correctly. If this command returns an error, proceed to the next step. 4. To open a DOS window, click the Start button, then Programs, then Accessories, and then Command Prompt. 5. To change to the bin directory, enter the following command at the prompt in the DOS window. c: cd \MATLAB7\BIN\WIN32 6. To update the registry, enter the following command. matlab /regserver 7. Start Maple and enter the command with(Matlab). If this command does not return a list of function names, review the first six steps. If problems persist, contact Maple Technical Support. Windows NT, 2000, and XP The following instructions describe how to set the path and update the Windows Registry. These instructions assume that you are logged on as an administrator and that MATLAB is installed on the C: drive in a directory called MATLAB. Substitute the appropriate drive letter and directory name if necessary. 1. To open the System Window in the Control Panel, click the Start button, then Settings, and then Control Panel. 2. Double-click System. 3. Specify user variables: - For Windows NT, in the System Properties dialog box, select the Environment tab. - For Windows 2000, select the Advanced tab and click the Environment Variables button. Look at the User Variables section. - For Windows XP, select Start>Control Panel>System. Click the Advanced tab. Double-click the Environment Variables button. Double-click Path. You must specify the correct version of MATLAB for the PATH. If there is an entry with Value PATH, then click that entry. Append the text c:\matlab7\bin\win32 to the Value field and click OK. Otherwise, add the text PATH to the Variable field, add the text c:\matlab7\bin\win32 to the Value field and click OK. 4. To restart the computer, click the Start button, then Shutdown, and then Restart. 5. Start Maple and enter the command with(Matlab). If this command returns a list of function names, then the Maple-MATLAB link is working correctly. If this command results in an error, proceed to the next step. 6. To open a DOS window, click the Start button, then Programs, then Accessories, and then Command Prompt. 7. To change to the bin directory, enter the following command at the prompt in the DOS window. c: cd \MATLAB7\BIN\WIN32 8. To update the registry, enter the following command. matlab /regserver 9. Start Maple and enter the command with(Matlab). If this command does not return a list of function names, review the first six steps. If problems persist, contact Maple Technical Support. Macintosh Location of MATLAB Installation The location of the MATLAB installation must be set in the Info.plist file, inside the Maple.app package. 1. Control-click the application icon (Maple 10.app) and select Show Package Contents from the context menu. 2. In the packages contents, open the Contents/Info.plist folder. 3. Find the lines (ll. 123-124): matlab.basedir 4. Between and , enter the base install directory of your MATLAB installation. For example, if MATLAB is installed in /Applications/MATLAB701, then the second line must be changed to /Applications/MATLAB701. 5. Save the file and restart Maple. Standard Worksheet - Execute the Matlab_setup script found in /Library/Frameworks/Maple.framework/Versions/10/bin. Command-Line Maple Some environment variables must be defined in the Maple script. The following instructions describe how to edit this script. These instructions assume that MATLAB is installed in /Applications/Matlab. Substitute the appropriate path if necessary. 1. Remove the comment characters (#) from the lines that look like the following example. MATLAB=/Applications/matlab export MATLAB 2. Locate your system type in the lines that follow the text in step 1. Remove the comment characters (#) from the appropriate lines for your system. The string "$MATLAB/extern/lib/$SYS" (where $SYS is your Macintosh platform) must resolve to a valid directory where the MATLAB shared libraries are located. The string "$MATLAB/bin" must resolve to a valid directory where the MATLAB binaries are located. UNIX and Linux Some environment variables must be defined in the Maple script $MAPLE/bin/maple. The following instructions describe how to edit this script. Use your favorite text editor that preserves line breaks. These instructions assume that MATLAB is installed in /usr/local/matlab. Substitute the appropriate path if necessary. 1. Remove the comment characters (#) from all lines mentioning MATLAB for a given platform, for example: MATLAB=/usr/local/matlab export MATLAB 2. Locate your system type in the lines that follow the text in step 1. Remove the comment characters (#) from the appropriate lines for your system. - The string "$MATLAB/extern/lib/$SYS" (where $SYS is your UNIX platform) must resolve to a valid directory where the MATLAB shared libraries are located. To locate the string, simply search for "$MATLAB/extern/lib". - The string "$MATLAB/bin" must resolve to a valid directory where the MATLAB binaries are located. - Remove the comment characters (#) from the lines LD_LIBRARY_PATH = ... and PATH = ... for your system type.
1 2 Page 1 of 2