Carl Love

Carl Love

28035 Reputation

25 Badges

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

MaplePrimes Activity


These are replies submitted by Carl Love

What do you want to achieve by placing an index, such as [maximum], on a non-atomic algebraic expression, such as (-k*a)? Maple does allow this, but I find it unwieldy, unless it's meant strictly for display purposes.

@Kitonum Note that the boundary of the region is in general the complicated and disconnected set {(x,y) | f(x,y) = c }. A general treatment of cases of polynomial might be possible with solve(..., parametric). I don't know how far beyond polynomial the capabilities of that command has been extended over the past few years.

@Preben Alsholm Thank you for your comments and your totally nontrivial digging through the dsolve code.

You wrote:

  • Maybe I'm misunderstanding your intention, but the localized version still knows about the parameter 'a' and that can still be set:

What I mean by A is an instantiation of X is that X is some structure with a free variable x (also known in mathematical language as a "parameter" (but "parameter" means some else in computer science)), and A is essentially a copy of X except that x has been given a specific value, a. The following two further things are irrelevant to my notion of an instantiation, but I think that you are trying to ascribe them to it:

  1. whether or not A can be further manipulated to change the parameter again;
  2. whether or not A retains enough of the original information of X that X could in theory be reconstructed (aka "reverse engineered") from A.

By the instantiation being localized, I mean that A has been saved or stored in such a way that if its parent X is instantiated again with a different value of x, this will not affect A.

These terms may have other definitions, and I may be using them incorrectly due to my having come up with the concepts independently (and, if so, I'd appreciate a correction).

Acer: Did you understand my previous usages to have the defintions above?

  • I thought that you wanted a procedure like the one you get when using dsolve/numeric for a concrete value of 'a'.

No. If that were feasible, then indeed it would serve my purpose, but I doubt that it's feasible, and I never considered it.

  • In fact Sol and res above are identical.

Yes, and that seems irrelevant to me. What's relevant is whether you can use the parent, Sol, to create res1 and res2 such that res1 and res2 exist in the same process's RAM at the same time and such that res1 <> res2 and furthermore they are not just superfically different (like Matrices with the same entries), but essentially different in that they act with different parameter values. You discovered a way to do that by using .m files. My technique does the same thing with %m formats, entirely in RAM. Yes, those procedures are quite long---this method does incur some significant overhead. Nonetheless, there is a substantial time savings.

  • Furthermore, if you use the "naive" approach, but add option remember it seems that you get good results for the plot3d problem.

It's only happenstance that your code works (produces the correct plot) because it's a sheer coincidence that plot3d happens to access the GRID coordinates in the order that minimizes the number the changes of the parameters. If you change the plot to

plot3d(Y(A,X), X= -2..2, A= -2..2, ...),

you'll see that your code gets it wrong while mine doesn't. In particular, yours acts as if the parameter remains unchanged after the final A value is first used.

 

 

 

 

Yes, instantiations can be localized, completely in RAM, using only the half-line of code given in the title and a remember table! This gives a brief solution to the timing anomaly that is the subject of this Post. Specifically, we can guarantee that dsolve's parameters will be set exactly once for each numeric valuation of the parameters, regardless of the order that plot3d (or any other code) chooses to evaluate the (independent variable, parameter) pairs.

restart: 
Sol:= dsolve({diff(y(x),x)=a*y(x), y(0)=1}, numeric, parameters= [a]):

#Naive method:
Y:= (A,X)-> 
   if [A,X]::[numeric$2] then Sol('parameters'= [A]); eval(:-y(:-x), Sol(X))
   else 'procname'(args)
   fi
:
gc():
P1:= CodeTools:-Usage(plot3d(Y(A,X), A= -2..2, X= -2..2, grid= [99$2])):

#Save data array to verify that the other method gives the same plot.
M1:= op([1,3], P1):
save M1, "/Users/carlj/desktop/M1.m":

memory used=325.30MiB, alloc change=4.00MiB, cpu time=2.84s, real time=2.84s, gc time=140.62ms


restart:
Sol:= dsolve({diff(y(x),x)=a*y(x), y(0)=1}, numeric, parameters= [a]):

#"Carl's Magic .m" method:
Localize:= proc(Sol, params::list(complexcons))
option remember;
   Sol('parameters'= params);
   sscanf(sprintf("%m", eval(Sol)), "%m")[]:
end proc:
Y:= (A,X)-> 
   `if`([A,X]::[numeric$2], eval(:-y(:-x), Localize(Sol, [A])(X)), 'procname'(args)):
gc():
P2:= CodeTools:-Usage(plot3d(Y(A,X), A= -2..2, X= -2..2, grid= [99$2])):

#Compare with saved plot data:
M2:= op([1,3], P2):
read "/Users/carlj/desktop/M1.m":

`Plot difference` = LinearAlgebra:-Norm(Matrix(M1-M2));

memory used=90.03MiB, alloc change=32.00MiB, cpu time=688.00ms, real time=699.00ms, gc time=31.25ms
                      Plot difference = 0.

 

Thank you for this valuable Post. I wonder if there's a way to localize dsolve's returned solution procedure(s) instantiated at particular parameter values. I tried:

Sol:= dsolve(..., numeric, parameters= [...]);
Sol(parameters= [case 1]);
Sol1:= copy(eval(Sol));
Sol(parameters= [
case 2]);
Sol2:= copy(eval(Sol));

But, alas, Sol1 now acts as if the case 2 parameters were in effect. I guess this means that the instantiated parameter values are global?

There are two characters appearing in the statement of Problem B1 that have been transcribed incorrectly. The first looks like numeral "2", and I'm sure that it's supposed to be the "is an element of" symbol. The second looks like "y", but I can't figure out what it's supposed to be.

Here is an example of the same thing done as what Mac Dude called a "module factory", i.e., a procedure that returns a module that implements some object (meant in the sense of Object-Oriented Programming or OOP):

CTS:= proc(Init::integer:= 0)
   module()
   local Counter::integer;
   export
      Inc:= proc(inc::integer:= 1) Counter:= Counter+inc end proc,
      Reset:= proc(init::integer:= Init) Counter:= init end proc,
      Query:= ()-> Counter
   ;
      Counter:= Init
   end module
end proc:

Sammy:= CTS(7):
Sammy:-Inc();
Sammy:-Query();
Sammy:-Reset();
                               8
                               8
                               7

Note that the code in significantly shorter, mostly because the module no longer needs to manage the names of the individual counters. The New has been replaced by the outer procedure itself. Note that the module contains one statement.

In terms of its behavior, this is very close to an object module, like I mentioned earlier. However, the syntax of an object module is significantly different.

@Rohith fsolve is a command that returns a purely numeric complex float solution to a system of equations that has the same number of equations as variables. The system of equations (or single equation) may be specified symbolically (as is the case here), or may be specified by a numeric procedure. When I referred to symbolic computation systems, I was referring to the ability to take a symbolic equation and use a one-line template to construct a procedure that numerically solves the equation. That process is symbolic, even though the final product is numeric.

However, no elementwise operators are going to work in Maple 12 because they were introduced in Maple 13. Constructions such as T +~ 1 can be replaced with map(`+`, T, 1).

@Ramakrishnan 

Almost everything that is done with a module could be done with a procedure. Here is an example:

Counters:= proc()::table(procedure);
local Counters::table(integer):= table();
   table([
      ':-Inc'= proc(C::name, inc::integer:= 1)
         if assigned(Counters[C]) then Counters[C]:= Counters[C]+inc
         else error "Unknown counter %1. Use New to create counters.", C
         fi
      end proc,
      ':-Reset'= proc(C::name, Init::integer:= 0)
         if assigned(Counters[C]) then Counters[C]:= Init
         else error "Unknown counter %1. Use New to create counters.", C
         fi
      end proc,
      ':-New'= proc(C::name, Init::integer:= 0)
         if assigned(Counters[C]) then
            error "Counter %1 already exists. Use GC to discard counters."
         else Counters[C]:= Init
         fi
      end proc,
      ':-GC'= proc(C::name)
      local r:= Counters[C];
         unassign('Counters[C]');
         r
      end proc,
      ':-Query'= ((C::name)-> Counters[C])
   ])
end proc:
   
CTS:= Counters():
CTS[New](Sammy, 7);
                               7
CTS[Inc](Sammy);
                               8
CTS[Query](Sammy);
                               8
CTS[Reset](Jane);
Error, (in CTS[Reset]) Unknown counter Jane. Use New to create counters.
CTS[GC](Sammy);
                               8
CTS[Query](Sammy);
                        Counters[Sammy]

Here is the same thing done as a module:

CTS:= module()
local Counters::table(integer):= table();
export
   Inc:= proc(C::name, inc::integer:= 1)
      if assigned(Counters[C]) then Counters[C]:= Counters[C]+inc
      else error "Unknown counter %1. Use New to create counters.", C
      fi
   end proc,
   Reset:= proc(C::name, Init::integer:= 0)
      if assigned(Counters[C]) then Counters[C]:= Init
      else error "Unknown counter %1. Use New to create counters.", C
      fi
   end proc,
   New:= proc(C::name, Init::integer:= 0)
      if assigned(Counters[C]) then
      error "Counter %1 already exists. Use GC to discard counters."
      else Counters[C]:= Init
      fi
   end proc,
   GC:= proc(C::name) local r:= Counters[C]; unassign('Counters[C]'); r end proc, 
   Query:= (C::name)-> Counters[C] 
; 
end module:

CTS[New](Sammy, 7);
                               7
CTS[Inc](Sammy);
                               8
CTS[Query](Sammy);
                               8
CTS[Reset](Jane);
Error, (in Reset) Unknown counter Jane. Use New to create counters.
CTS[GC](Sammy);
                               8
CTS[Query](Sammy);
                        Counters[Sammy]

Note that this module has no statements, only declarations. The vast majority of modules that I write either have no statements, or they have the single statement ModuleLoad().

The above module could be (and most likely would be) implemented as a module with option object. Then the local would be a single integer variable rather than a table of them, and the New would create a new copy of the module (with a fresh, independent local variable). The syntax required for this is a bit elaborate, so I think that it's best to get comfortable with regular modules before learning object modules. Anyway, it can all ultimately be done with regular modules or even procedures, as shown above.

In addition to what Joe said, if the resulting expression has exponents, then your professor's instruction to "Use your identities ... to eliminate all exponents" can be done by simple application of the combine command (no extra options needed). I don't have Maple open right now (grocery shopping) to check whether there's some snag in this case, but that's usually what combine does.

Note that the "Fourier sine transform" and "Fourier cosine transform" are themselves transforms and they are not the same thing as the Fourier transform of sine or cosine. From your wording it's not clear that you're aware of the distinction. 

@vv Vote up. But your procedure will benefit greatly by using option remember, as is usually the case with a branched recursion.

@Alger Declare the matrix with storage= sparse:

m2:= Matrix((150000, 150000), storage= sparse);

@vv Threads:-Seq can get bogged down when the sequence is short. The tasksize option helps with this (example below). But, still, it seems to work best for long sequences rather than short sequences containing long tasks.

When using CodeTools:-Usage for measuring times and memory for GrId operations, the numbers only apply to the master process, so only "real time" is realistic. For finer measurement, you need to do the measuring within the individual processes (example below). 

I changed your example to use evalhf and I increased each add by a factor of 100.

f := proc(i) local k; 
if   i=1 then    add(1/(k+sin(k))^(k/(k+1)),k=1..5*10^6)
elif i=2 then    add(1/(k+sin(k))^(k/(k+2)),k=1..6*10^6)
elif i=3 then    add(1/(k+sin(k))^(k/(k+3)),k=1..6*10^6)
elif i=4 then    add(1/(k+sin(k))^(k/(k+4)),k=1..3*10^6)
fi
end:

CodeTools:-Usage([Threads:-Seq[tasksize=1](evalhf(f(i)), i=1..4)]);
CodeTools:-Usage([Grid:-Seq(CodeTools:-Usage(evalhf(f(i))), i= 1..4)]);
CodeTools:-Usage([seq(evalhf(f(i)), i=1..4)]);  

memory used=3.60KiB, alloc change=0 bytes, cpu time=13.66s, real time=3.93s, gc time=0ns
[16.5582269340421213, 17.6172669486901476, 18.3916368704668471, 18.4091417194700675]

memory used=0.91KiB, alloc change=0 bytes, cpu time=797.00ms, real time=813.00ms, gc time=0ns
memory used=0.91KiB, alloc change=0 bytes, cpu time=1.33s, real time=1.34s, gc time=0ns
memory used=1.05KiB, alloc change=0 bytes, cpu time=1.62s, real time=1.63s, gc time=0ns
memory used=0.91KiB, alloc change=0 bytes, cpu time=1.62s, real time=1.63s, gc time=0ns
memory used=177.05KiB, alloc change=2.19MiB, cpu time=156.00ms, real time=1.68s, gc time=125.00ms
[16.5582269340421213, 17.6172669486901476, 18.3916368704668471, 18.4091417194700675]

memory used=1.44KiB, alloc change=0 bytes, cpu time=5.05s, real time=5.07s, gc time=0ns
[16.5582269340421213, 17.6172669486901476, 18.3916368704668471, 18.4091417194700675]

 

First 289 290 291 292 293 294 295 Last Page 291 of 708