Language & Programming Updates in Maple 2022
|
ArrayTools
|
|
|
Lookup
|
|
•
|
The new Lookup command searches for a specified value in a 1-D container or row/column of a 2-D container, and for all the matches, looks up and returns the corresponding values in another 1-D container or row/column of the same 2-D container. Various options provide flexibility as to what registers as a match.
|
•
|
The default type of match is exact, and for a Matrix or 2-D Array, the default is to search for matches in column 2, and look up the corresponding values for matches in column 1:
|
>
|
A := Matrix( [["a",1,2,3],["b",3,1,2],["c",2,3,1]] );
|
>
|
Lookup( 2, A, 'column', 4, 1 );
|
•
|
When floats are involved, floating-point comparisons can be used (and tolerance can be modified with the digits, ulps, and relativeerror options):
|
>
|
A := [ sqrt(2), evalf(sqrt(2)), sqrt(3), evalf(sqrt(3)) ];
|
| (4) |
>
|
B := [ 10, 20, 30, 40 ];
|
| (5) |
>
|
Lookup( sqrt(2), A, B, 'match' = 'exact' );
|
>
|
Lookup( sqrt(2), A, B, 'match' = 'float' );
|
•
|
Regular expressions and wildcards can be used to match strings:
|
>
|
A := [ "ab", "abc", "ad", "abbc", "a2c", "aBc" ];
|
| (8) |
>
|
B := [ 10, 20, 30, 40, 50, 60 ];
|
| (9) |
>
|
Lookup( "(^)(a)([a-z]+)(c)($)", A, B, 'match' = 'regexp' );
|
>
|
Lookup( "a*c", A, B, 'match' = 'wildcard' );
|
•
|
Searches, by default, are performed in the forward direction, but can also be performed in reverse:
|
>
|
Lookup( "a*c", A, B, 'match' = 'wildcard', 'direction' = 'reverse' );
|
•
|
Furthermore, we can request that results be restricted to a certain quantity or even a range:
|
>
|
Lookup( "a*c", A, B, 'match' = 'wildcard', 'numresults' = 2 );
|
>
|
Lookup( "a*c", A, B, 'match' = 'wildcard', 'numresults' = 0 .. 2 );
|
•
|
DataFrames are also supported with the default for search being column 1 and lookup being in the row labels. Consider this DataFrame with batting statistics for the 2021 Toronto Blue Jay hitters with 100 or more at bats:
|
>
|
Data := Matrix([[0.242,165,19,40,8,0,8,24,19,0.328,0.436],[0.298,640,121,191,30,1,29,102,40,0.343,0.484],[0.224,250,27,56,10,1,7,27,37,0.322,0.356],[0.282,131,16,37,6,2,4,15,9,0.329,0.45],[0.223,184,32,41,13,0,11,28,17,0.299,0.473],[0.264,299,59,79,19,1,22,50,37,0.352,0.555],[0.246,114,9,28,6,0,2,11,8,0.293,0.351],[0.276,500,62,138,28,2,21,84,32,0.319,0.466],[0.265,652,115,173,39,2,45,102,66,0.334,0.538],[0.241,511,59,123,25,1,22,81,27,0.281,0.423],[20.53,198,22,50,15,0,1,10,15,0.31,0.343],[0.209,139,12,29,4,1,4,8,9,0.272,0.338],[0.311,222,32,69,13,1,2,17,22,0.376,0.405],[0.296,550,92,163,29,0,32,116,36,0.346,0.524],[0.311,604,123,188,29,1,48,111,86,0.401,0.601]]):
|
>
|
Players := ["Alejandro Kirk","Bo Bichette","Cavan Biggio","Corey Dickerson","Danny Jansen","George Springer","Joe Panik","Lourdes Gurriel Jr","Marcus Semien","Randal Grichuk","Reese McGuire","Rowdy Tellez","Santiago Espinal","Teoscar Hernandez","Vladimir Guerrero Jr"]:
|
>
|
Categories := ["AVG","AB","R","H","2B","3B","HR","RBI","BB","OBP","SLG"]:
|
>
|
DF := DataFrame( Data, 'rows' = Players, 'columns' = Categories );
|
•
|
To determine the players with 30 or more home runs or 100 or more RBIs, we can pass a custom matching procedure:
|
>
|
Lookup( 30, DF, "HR", 'match' = `>=` );
|
| (16) |
>
|
Lookup( 100, DF, "RBI", 'match' = `>=` );
|
| (17) |
|
|
Reverse
|
|
>
|
A := LinearAlgebra:-RandomVector( 10^5 );
|
>
|
CodeTools:-Usage( ArrayTools:-Reverse( A ), 'iterations' = 25 );
|
memory used=0.76MiB, alloc change=17.61MiB, cpu time=560.00us, real time=560.00us, gc time=0ns
| |
|
|
|
The MultivariatePowerSeries Package
|
|
>
|
with(MultivariatePowerSeries):
|
|
Creating PowerSeries Objects from Arbitrary Expressions
|
|
•
|
PowerSeries objects can now be created from arbitrary expressions, not just polynomials--as long as the expression has a power series representation at the origin in all of the variables, and that representation can be found by the series command.
|
>
|
ps_exp := PowerSeries(exp(x));
|
| (20) |
>
|
ps_sin := PowerSeries(sin(x + y - 2*y*z));
|
| (22) |
| (23) |
|
|
Substituting into a PowerSeries Object
|
|
•
|
The Substitute command can substitute a power series (or a polynomial) into a PowerSeries object. This works only if one or both of the following conditions are satisfied: the substituted power series is not invertible, or the power series that we substitute into knows its analytic expression.
|
>
|
ps_exp_2 := Substitute(x = PowerSeries(2*x/(1-y)), ps_exp);
|
| (24) |
| (25) |
>
|
ps_exp_3 := Substitute(x = ps_exp, ps_exp);
|
| (26) |
| (27) |
•
|
A Taylor shift is a substitution of for , where is a variable and is a constant. There is a separate command for such substitutions:
|
>
|
ps_exp_4 := TaylorShift(ps_exp, x = Pi*I/2);
|
| (28) |
|
|
|
Additional Updates
|
|
|
Type foreign
|
|
•
|
The data type foreign was added, for so-called "foreign DAGs". These are used to encapsulate some data structures that do not originate in Maple itself, but in other programs or libraries. For example, data structures coming from Python that are not automatically translated to their Maple equivalents. This also applies to some internals of the RealBox and ComplexBox objects, which are also new in 2022.
|
>
|
dictionary := Python:-EvalString("{}");
|
| (30) |
>
|
type(dictionary, foreign);
|
|
|
The LinearAlgebra Package
|
|
•
|
The CompressedSparseForm command in the LinearAlgebra package received some new options to fine-tune the result, called length0, includediagonal, and structuralsymmetry. They force the command to include certain entries in the output, even if the corresponding matrix entry is 0.
|
>
|
A := Matrix([[1, 2, 0], [2, 0, 3], [0, 0, -1]], datatype=integer[4]):
|
•
|
By default, only the five nonzero entries in A are included in the output.
|
>
|
CompressedSparseForm(A);
|
•
|
When we specify the includediagonal option, any zero entries on the diagonal are also included; in this case, . The structuralsymmetry option ensures that whenever is included, so is . For this matrix, that means that is included, even though it is zero.
|
>
|
CompressedSparseForm(A, includediagonal, structuralsymmetry);
|
| (33) |
|
|
Initializing Paired Local Declarations
|
|
•
|
When declaring a local variable inside a procedure, you have long been able to also assign each variable a value if you choose. New in Maple 2022 is the ability to assign a sequence of local variables to the output of a single function call.
|
>
|
split := proc( i )
local (p, np) := selectremove(isprime,i);
[p,np];
end proc:
|
>
|
split([1,2,3,4,5,6,7]);
|
| (34) |
|
|
|