Joe Riel

7722 Reputation

22 Badges

14 years, 138 days

MaplePrimes Activity


These are replies submitted by Joe Riel

@acer For consistency, I'd probably use algsubs for the first case as well. There should be a nicer way to do this. One could use applyop, but it is too syntactical:

applyop(eval, -1, work, h=0);

Better might be an applydenom function, but it probably isn't useful enough to bother writing. Maybe the better approach is

mtaylor(work, h, 2);

applied to the result of the integral. The second substitution can be achieved with

simplify(work, {g = G*M/R^2}, [G]);

@vv While I'm not convinced of the importance of that operation, here is a way to do that without creating new mutable elements.

# Combining the following two steps into a single step generates a set with only two Vectors
# because Maple's simplifier removes the "duplicate" before the Vector is generated.
S := <1>, <1>, <2>:
S := {S}:
S := {entries(table([seq(convert(x,list)=x, x = S)]), 'nolist')};

@vv Nice workaround. Here's maybe a clearer way to convert indexed names to symbols:

sys1 := subsindets(sys, indexed, convert, symbol);

@John Fredsted It's unfortunate that that there is no way to pass the third argument to coeffs, to assign the terms of p, without passing the optional second argument. One could pass indets(p) to coeffs.  Here's a variation that collects the terms that have a common coefficient. 

C := [coeffs](p,indets(p),'T'):
A := add(``(C[i])*T[i], i=1..numelems(C)):
collect(A, ``~(C));

@MDD Am not quite comprehending what you are asking for.

@Kitonum Slighty shorter is

map(rhs=lhs, S);

@Carl Love I took the term (Topological Sorting) from Knuth, see section 2.2.3 of The Art Of Computer Programming, though don't believe it originated with him. I assumed it came from the topology of a dag and its associated partial ordering. There is a Maple procedure, TopologicalSort, that is related but only returns one possible linear ordering that meets the constraints (rather than all of them).

@Carl Love The efficiency is space-wise; a static procedure definition is shared by all the objects of a given object type. That isn't the case for non-static procedures.

My comment about posting on objects was in regard to the use of function to which acer alluded. More later.

In considering your idea of extending two-parameter eval to allow records as the second parameter, there is an interesting aspect to it.  Record field names are not unique in the way that regular names are; they can match both local and global symbols. Effectively they match the string corresponding to the field name.  That isn't necessarily a problem, though it would presumably make it significantly more expensive to eval an arbitrary expression using a record to define the eqns.  For efficiency one might restrict the matching to globals but that seems less useful.   

Further Most of what I was considering about object methods, particularly the use of function, is better described in the help page ?Object,function_mechanism. The quick summary is that foo(obj, ...) can fail if the global name foo has been assigned (say by the user) to an expression.  One can avoid that by using function:-foo(obj, ...).  Of course, one could also avoid it by using obj:-foo(obj, ...), however, there are situations where that doesn't work, say you were mapping a generic method over a list of objects. Using map(foo, [obj1,obj2]) is not robust in that the global foo might be assigned an expression. Using   map(obj1:-foo, [obj1, obj2]) doesn't work if the objects are of different classes.  Using map(function:-foo, [obj1, obj2]) works. 

@Carl Love I'm not wild about dropping the static modifier, for efficiency.  I understand your issue with the pobj prefix; it took me a while to get used to not seeing it, then learned (the hard way) that, when using objects in code (versus in a worksheet) it should be retained, for robustness.  The duplication annoys.  I should post something about that.

@Carl Love Interesting point, about eval'ing with respect to a record (seems like allowing a module might be overkill and introduce some weird issues). Here's what you're suggesting (note the change to ModuleApply to ignore undefined parameters):

KandR:= module()
local ModuleApply, Params, params;
export Eval;

    params:= Record(a::algebraic, b::algebraic, c::algebraic, e::algebraic);
    Params:= [exports(params)];

    # procedure that lets user set parameter values:
    ModuleApply:= proc()
    local A, p, savAL:= kernelopts('assertlevel'= 2);
        for A in args do
            if A :: equation then
                p := cat("",lhs(A));
                if member(p, params) then
                    params[p] := rhs(A);
                end if;
            end if;
        end do;
        kernelopts('assertlevel'= savAL);
        return
    end proc;

    Eval := proc(e)
        eval(e, Params =~ map2(index, params, Params));
    end proc;

end module:

KandR(x = 3, a=2, b=1);

KandR:-Eval(3*a + b + c);
                  7 + (c::algebraic)

The handling of an unassigned parameter (c) is not nice and would need to be cleaned up. 

Note that it should be possible to implement this using objects, by overloading eval, however, that doesn't address the more fundamental operation you are looking for.

Here's the partial implementation as an object

ParamObj := module()
option object;
local eqs := NULL;
export
    ModuleApply :: static := proc()
        Object(ParamObj,_passed);
    end proc;

export
    ModuleCopy :: static := proc(self :: ParamObj
                                 , proto :: ParamObj
                                 , eqs :: seq(name = anything)
                                )
        self:-eqs := eqs;
    end proc;

export
    eval :: static := proc(x :: anything, self :: ParamObj)
        :-eval(x, [self:-eqs]);
    end proc;
end module:

pobj := ParamObj(a=1, b=2);

pobj:-eval(a+b+c, pobj);
                        3 + c

The problem there is that I cheated. One should be able to call this using

eval(a+b+c, pobj);

Alas, that doesn't work, it raises an error, probably because eval doesn't automatically dispatch to an object method unless the first parameter is the object (I'm guessing, haven't tried it).

@Carl Love Thanks, another new tidbit. It was introduced in Maple2017, so hasn't stuck yet in my brain. 

@acer The use of the ?[] operator is the key.  It's not an easy function to find in the Maple help hierarchy, at least not without some foreknowledge (see ?use).  Note that replacing 'name' with 'symbol' makes the operation idempotent, which might be useful.

@Carl Love Nice.  I never realized that mod can be extended with user defined functions.

You omitted some steps.  Probably you did

(volts,other) := Solve(ckt,'ac','returnall'):

But that works for me, that is, BodePlot(sys) works fine. What version of Syrup do you have (Syrup:-Version)?

@Ronan Actually, I was wrong about what Maple does with (x^2+y^2=1)^2.  It distributes the power over the equality to get (x^2+y^2)^2=1. The implicitplot function converts an equation to an expression equal to zero, so that becomes (x^2+y^2)^2-1.  Solving that numerically is not an issue.  I assume what  you want to do is to convert f(x)^n = 0 to the equivalent (for n > 0) f(x) = 0, possibly with the equation implied.  You could write a simple procedure that does that:

   reduce := proc(x) 
       if x :: 'anything^positive' then 
           op(1,x);
       else 
           x; 
       end if; 
    end proc: 
5 6 7 8 9 10 11 Last Page 7 of 177