nm

8552 Reputation

19 Badges

12 years, 349 days

MaplePrimes Activity


These are questions asked by nm

In traditional OOP, one can have a base class with its own constructor. Then extends this class, where the sub class has also its own consturctor. The first thing one does in the extending class constructor is to initialize the base class by calling base class constructor directly, before finishing the initializing of the extending class.

This is done in different ways. in Java the call super(...) is used for example. in C++ it is done by explicit call to base class constructor. Here is an example.  from the net.

But in Maple, I am not able to duplicate this. Because once ModuleCopy is defined (which is the name for the module constructor) in the base class, I can't have another ModuleCopy in the extending/child class. Maple complains because the name already exists.

In the following example, the base class represents a generic ode.

Then the extending/child class is meant to represent a first order ode which extends the base class and adds some specific functions that only meant to apply for first order ode type.

Later on I want to make a second order ode class and so on. All extend the base ode class. 

My question is: How to extend a class in Maple and have the extending/child class constructor call the base class constructor if one can't have more than one constructor when extending?

This Maple help shows one example of inhertance using Objects but this example does not use a constructor in the base of the child. I am assuming one needs to use ModuleCopy as the name for the constuctor since it specifies how an object is copied by Object so can't make my own function and pretend it is the constructor.

restart;

interface(version)

`Standard Worksheet Interface, Maple 2023.0, Windows 10, March 6 2023 Build ID 1689885`

ode_class:=module()
   option object;
   local ode::`=`;
   local x::symbol;
   local y::symbol;

   #constructor
   export ModuleCopy::static := proc( _self::ode_class, proto::ode_class, ode, func, $ )
    _self:-ode:= ode;
    _self:-y:=op(0,func);
    _self:-x:=op(1,func);
   end proc;

   export get_ode::static:=proc(_self,$)
     return _self:-ode;
   end proc;

   export get_x::static:=proc(_self,$)
     return _self:-x;
   end proc;

   export get_y::static:=proc(_self,$)
     return _self:-y;
   end proc;


end module;

_m2586207352192

first_order_ode_class:=module()
   option object(ode_class);
   local is_linear_ode::truefalse;

   #constructor
   export ModuleCopy::static := proc( _self::first_order_ode_class, proto::first_order_ode_class, ode, func, $ )
    #How to call base class above constructor here?

    _self:-is_linear_ode:= false;
   end proc;

   export is_linear::static:=proc(_self,$)
          return _self:-is_linear_ode;
   end proc;
          
end module;

Error, (in first_order_ode_class) export `ModuleCopy` is declared more than once

ode:=Object(first_order_ode_class,diff(y(x),x)=sin(x),y(x));

_m2586207319808

ode:-get_ode();
ode:-is_linear()

false

 


Download base_class_constructor.mw

UPDATE

This is workaround which seems to work OK. do not use ModuleCopy to construct an object, but have custom named function for each base and each child and call these explicitly.

So child constructor will  now call its parent constuctor using the specific name of that function. May be using some convention as  module_name_constuctor(....)   passing it what the parents needs.

The drawback is that now copying an object does not work automatically since ModuleCopy is missing.  but so far, I never had the need to copy one object to another, so I can live without it for now.
 

1421372

restart;

1421372

ode_class:=module()
   option object;
   local ode::`=`;
   local x::symbol;
   local y::symbol;

   #constructor
   export ode_constructor::static := proc( _self,ode::`=`, func, $ )
     print("inside ode_class constrructor");
    _self:-ode:= ode;
    _self:-y:=op(0,func);
    _self:-x:=op(1,func);
    NULL;
   end proc;

   export get_ode::static:=proc(_self,$)
     return _self:-ode;
   end proc;

   export get_x::static:=proc(_self,$)
     return _self:-x;
   end proc;

   export get_y::static:=proc(_self,$)
     return _self:-y;
   end proc;

end module;

_m2325067887904

first_order_ode_class:=module()
   option object(ode_class);
   local is_linear_ode::truefalse;

   #constructor
   export first_order_ode_constructor::static := proc( _self,ode::`=`, func, $ )
      print("inside first_order_ode_class constrructor");
      #call base class constructor
      _self:-ode_constructor(ode,func);
      #finish rest of constructor  
     _self:-is_linear_ode:= false;
     NULL;
   end proc;

   export is_linear::static:=proc(_self,$)
          return _self:-is_linear_ode;
   end proc:
          
end module;

_m2325067872672

o:=Object(first_order_ode_class);
o:-first_order_ode_constructor(diff(y(x),x)=1,y(x));

_m2325067860896

"inside first_order_ode_class constrructor"

"inside ode_class constrructor"

o:-get_ode()

diff(y(x), x) = 1

o:-is_linear()

false

 


I think Maple OOP is not fully OOP,  but it is better than nothing.

Download base_class_no_constructor.mw

 

I was translating some code from Mathematica to Maple. Why MmaTranslator does not know about Mathematica's CubeRoot function? This was added in 2012 (more than 11 years ago).

Is this known? How could one teach Maple's MmaTranslator to convert CubeRoot[x] to surd(x,3)? Is it possible to manually add missing translations to this package? Otherwise I would have to manually edit lots of code and do this myself each time.

 

restart; 
with(MmaTranslator);
FromMma(`CubeRoot[9]`);

Gives CubeRoot(9) it should be surd(9, 3)

Version 2023 on windows 10

Is there a mathematical reason why Maple does not allow expansion point for solving an ode using series solution to be different than where initial conditions are located?

I do not see why this restriction is there. Here is first order ode, where expansion point is x=1 and initial condiitons are also at x=1

restart;
ode:=diff(y(x),x)=x^3;
dsolve([ode,y(1)=1],y(x),'series',x=1)

            y(x) = (1 + (x - 1)) + 3/2*(x - 1)^2 + (x - 1)^3 + 1/4*(x - 1)^4 + O((x - 1)^6)

No problem. But when expansion point at x=0, it complains

restart;
ode:=diff(y(x),x)=x^3;
dsolve([ode,y(1)=1],y(x),'series',x=0)

Error, (in dsolve/SERIES) conflicting specifications of the series expansion point: 1 v.s. 0

I know help mentions that it uses initial conditions point for expansion if given, and if no IC is given, then it uses x=point if given and if no x=point is given then it default to x=0.

But my question is, why it does not handle the case when the expansion point is given explicitly and is at a different location than where IC are given? Is this simply just a feature missing that could be added in a future release if needed, or is it due to some mathematical reason that I do not see?

I would have expected it to first find the series solution around the given expansion point, then use the IC to determine the unknown constant after that, just like we normally do when solving an ode using standard methods not using series expansion.

I am using Maple 2023

Another very strange behavior.

res:= x^2 + x + 1 + 1/3*x^3 + 1/12*x^4 + 1/60*x^5 + 1/360*x^6 + 1/2520*x^7;
sort(res);

#and now
res

Without trying it, what do you expect the output of the last line above to be?  The same as the first one, right?  But that is not what Maple gives. Maple now changes res to always be sorted, even though I have not reassigned it.

Does this mean if one calls sort(), then all the variables that contains polynomials will also be sorted automatically?

Unable to upload worksheet. So here is screen shot

 


Download sort_problem.mw

These give errors

limit(y(0),y(0)=1)

limit(y(x),y(x)=1)

Error, (in limit) limit variable previously assigned, 2nd argument evaluates to y(0) = 1
 

One has to write 

limit(y,y=1)

But why? Is this because y(x) is not considered "algebraic" ? 

Mathematica has no problem with either one of these

I found this when I was trying to find the limit at initial conditions, when x=0 and y(0)=1 and wanted to take the limit on both x->0 and y(0)->1 

I can easily code around this, by renaming y(0) to say Y0 and then the limit will work.

It just seems to be unnecessary restriction of the limit() command parsing ability. 

What is the logic behind not allowing one to write limit(y(x),y(x)=1) ? 

First 15 16 17 18 19 20 21 Last Page 17 of 164