Language & Programming Updates in Maple 2022
ArrayTools
The MultivariatePowerSeries Package
Additional Updates
with( 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]] );
A≔a123b312c231
Lookup( 2, A );
c
Lookup( 2, A, 'column', 4, 1 );
b
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)) ];
A≔2,1.414213562,3,1.732050808
B := [ 10, 20, 30, 40 ];
B≔10,20,30,40
Lookup( sqrt(2), A, B, 'match' = 'exact' );
10
Lookup( sqrt(2), A, B, 'match' = 'float' );
10,20
Regular expressions and wildcards can be used to match strings:
A := [ "ab", "abc", "ad", "abbc", "a2c", "aBc" ];
A≔ab,abc,ad,abbc,a2c,aBc
B := [ 10, 20, 30, 40, 50, 60 ];
B≔10,20,30,40,50,60
Lookup( "(^)(a)([a-z]+)(c)($)", A, B, 'match' = 'regexp' );
20,40
Lookup( "a*c", A, B, 'match' = 'wildcard' );
20,40,50,60
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' );
60,50,40,20
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' = `>=` );
Marcus Semien,Teoscar Hernandez,Vladimir Guerrero Jr
Lookup( 100, DF, "RBI", 'match' = `>=` );
Bo Bichette,Marcus Semien,Teoscar Hernandez,Vladimir Guerrero Jr
Reverse
The Reverse command has been optimized to run using compiled code, and now executes much more quickly. For more information, see the performance update page.
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 was added for Maple 2021. It received a number of updates for 2022.
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));
ps_exp≔PowⅇrSⅇrⅈⅇs of ⅇx : 1+x+x22+x36+x424+x5120+…
Truncate(ps_exp, 3);
1+x+12⁢x2+16⁢x3
ps_sin := PowerSeries(sin(x + y - 2*y*z));
ps_sin≔PowⅇrSⅇrⅈⅇs of −2⁢sin⁡⁡…⁢…⁢cos⁡y+…−cos⁡x⁢sin⁡y : x+y−2⁢y⁢z−x⁢y22−x36−y36−x2⁢y2+x2⁢y⁢z+2⁢x⁢z⁢y2+z⁢y3+x⁢y424−2⁢x⁢y2⁢z2+x3⁢y212+x5120+y5120−2⁢z2⁢y3+x2⁢y312+x4⁢y24+…
Truncate(ps_sin, 3);
x+y−2⁢y⁢z−12⁢x⁢y2−16⁢x3−16⁢y3−12⁢x2⁢y
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);
ps_exp_2≔PowⅇrSⅇrⅈⅇs of ⅇ−2⁢x−1+y : 1+…
Truncate(ps_exp_2, 3);
1+2⁢x+2⁢x2+2⁢x⁢y+43⁢x3+4⁢x2⁢y+2⁢x⁢y2
ps_exp_3 := Substitute(x = ps_exp, ps_exp);
ps_exp_3≔PowⅇrSⅇrⅈⅇs of ⅇⅇx : ⅇ+…
Truncate(ps_exp_3, 3);
ⅇ+ⅇ⁢x+ⅇ⁢x2+5⁢ⅇ⁢x36
A Taylor shift is a substitution of x+c for x, where x is a variable and c is a constant. There is a separate command for such substitutions:
ps_exp_4 := TaylorShift(ps_exp, x = Pi*I/2);
ps_exp_4≔PowⅇrSⅇrⅈⅇs of ⅇx+I⁢π2 : I+I⁢x+I2⁢x2+I6⁢x3+I24⁢x4+I120⁢x5+…
Truncate(ps_exp_4, 3);
I+I⁢x+I⁢x22+I⁢x36
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("{}");
dictionary≔<Python object: {}>
type(dictionary, foreign);
true
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.
with(LinearAlgebra):
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);
1346,12123,1223−1
When we specify the includediagonal option, any zero entries on the diagonal are also included; in this case, A2,2. The structuralsymmetry option ensures that whenever Ai,j is included, so is Aj,i. For this matrix, that means that A3,2 is included, even though it is zero.
CompressedSparseForm(A, includediagonal, structuralsymmetry);
1368,1212323,122003−1
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]);
2,3,5,7,1,4,6
Download Help Document