Performance - New Features in Maple 2019 - Maplesoft

What's New in Maple 2019

Performance

Maple 2019 improves the performance of many routines. 



factor 

Maple 2019 includes performance improvements for factoring sparse multivariate polynomials with integer coefficients.  

> vars := [seq(x[i], i = 1 .. 8)]
 

Typesetting:-mprintslash([vars := [x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]]], [[x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]]])
 

> g := randpoly(vars, degree = 15, terms = 50, coeffs = rand(-1000 .. 1000))
 

Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
Typesetting:-mprintslash([g := `+`(`*`(555, `*`(`^`(x[1], 4), `*`(x[2], `*`(`^`(x[3], 2), `*`(`^`(x[5], 3), `*`(`^`(x[6], 2), `*`(x[7], `*`(`^`(x[8], 2))))))))), `*`(771, `*`(`^`(x[1], 4), `*`(x[2], `...
 

> h := randpoly(vars, degree = 15, terms = 50, coeffs = rand(-1000 .. 1000))
 

Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
Typesetting:-mprintslash([h := `+`(`-`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2)))))))), `*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(...
 

> f := expand(`*`(g, `*`(h))); -1
 

The following factorization took about 5 seconds in Maple 2018 on the same machine. 

> CodeTools:-Usage(factor(f))
 

 

memory used=40.03MiB, alloc change=41.09MiB, cpu time=250.00ms, real time=247.00ms, gc time=0ns
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
`*`(`+`(`*`(474, `*`(`^`(x[1], 5), `*`(`^`(x[3], 4), `*`(`^`(x[4], 3), `*`(x[5], `*`(`^`(x[6], 2))))))), `-`(`*`(429, `*`(`^`(x[1], 4), `*`(`^`(x[2], 2), `*`(x[3], `*`(`^`(x[6], 4), `*`(`^`(x[7], 3), ...
 

A larger example, with about 30000 terms. 

> f := expand(mul(`+`(randpoly([seq(x[j], j = 1 .. 12)], degree = 15, terms = 30, coeffs = rand(1 .. 100000)), i), i = 1 .. 3)); -1
 

> nops(f)
 

29791
 

This factorization took more than 1 minute in Maple 2018. 

> F := CodeTools:-Usage(factor(f)); -1
 

memory used=475.20MiB, alloc change=133.50MiB, cpu time=3.29s, real time=3.08s, gc time=468.00ms
 

> nops(F)
 

3
 

The last example is the determinant of a generic circulant matrix, i.e., where all entries are indeterminates, and each row is a cyclic rotation of the first one. 

> with(LinearAlgebra); -1; interface(rtablesize = 12); -1
 

> A := Matrix(12, shape = Circulant[[seq(x[j], j = 1 .. 12)]])
 

Typesetting:-mfenced(Typesetting:-mrow(Typesetting:-mtable(Typesetting:-mtr(Typesetting:-mtd(Typesetting:-msub(Typesetting:-mi(
 

> f := Determinant(A, method = minor); -1
 

> nops(f)
 

86500
 

This factorization took about 17 seconds in Maple 2018. 

> F := CodeTools:-Usage(factor(f)); -1
 

memory used=488.25MiB, alloc change=-41.44MiB, cpu time=5.37s, real time=3.96s, gc time=421.20ms
 

> nops(F)
 

6
 

> map(nops, [op(F)])
 

[12, 12, 42, 78, 78, 621]
 

> map(degree, [op(F)])
 

[1, 1, 2, 2, 2, 4]
 

> expand(`+`(f, `-`(F)))
 

0
 

Graph Theory 

In Maple 2019 the MaximumClique function of the GraphTheory package has new algorithms for computing the maximum clique of a graph and an option to choose the algorithm that you want to use, giving a huge performance boost on certain kinds of graphs. In the following example, Maple 2019 almost instantly finds the maximum clique of a graph that Maple 2018 needed over 3 minutes to find. In this case the "sat" method is used which translates the problem into Boolean logic and solves the resulting satisfiability problem using a SAT solver. 

> with(GraphTheory); -1
 

> filename := FileTools:-JoinPath([kernelopts(datadir),
 

Typesetting:-mprintslash([filename :=
 

> G := ImportGraph(filename, 'dimacs')
 

Typesetting:-mprintslash([G := `Graph 1: an undirected unweighted graph with 45 vertices and 918 edge(s)`], [GRAPHLN(undirected, unweighted, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,...
 

> DegreeSequence(G)
 

[40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41]
[40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41]
 

> C := CodeTools:-Usage(MaximumClique(G, method = 'sat'))
 

 

memory used=10.44MiB, alloc change=28.99MiB, cpu time=187.00ms, real time=152.00ms, gc time=62.40ms
Typesetting:-mprintslash([C := [2, 3, 4, 6, 10, 14, 17, 20, 24, 25, 30, 33, 36, 39, 41, 45]], [[2, 3, 4, 6, 10, 14, 17, 20, 24, 25, 30, 33, 36, 39, 41, 45]])
 

> numelems(C)
 

16
 

Group Theory 

  • Arithmetic and other low-level operations for permutations have been completely re-written in compiled kernel code. In addition, the memory overhead of permutations has been considerably reduced.
 

  • For example, the following call to PermOrder took about 200 times longer in Maple 2018.
 

> with(GroupTheory); -1
 

> p := Perm(combinat:-randperm(`^`(10, 5))); -1
 

> PermOrder(p)
 

47396163561937236086040
 

  • Timing details will of course vary from one machine to another, and depend also upon the random state of the Maple session. But, reproduced here are some representative calculations run in a fresh Maple 2018 session,  on a particular 64-bit Linux workstation.
 

> L := CodeTools:-Usage(([seq])(Perm(combinat:-randperm(`^`(10, 4))), i = 1 .. 1000)); -1
 

> CodeTools:-Usage(PermProduct(op(L))); -1
 

`memory used=307.57MiB, alloc change=288.00MiB, cpu time=9.78s, real time=8.36s, gc time=1.75s`
 

> CodeTools:-Usage(map(PermOrder, L)); -1
 

`memory used=2.54GiB, alloc change=96.00MiB, cpu time=52.62s, real time=40.96s, gc time=13.75s`
 

> CodeTools:-Usage(map(PermInverse, L)); -1
 

`memory used=0.74GiB, alloc change=320.00MiB, cpu time=19.56s, real time=14.66s, gc time=5.71s`
 

> CodeTools:-Usage(map(PermCycleType, L)); -1
 

`memory used=0.84MiB, alloc change=0 bytes, cpu time=152.00ms, real time=149.00ms, gc time=0ns`
 

> CodeTools:-Usage(map(PermPower, L, 3333)); -1
 

`memory used=4.53GiB, alloc change=2.22GiB, cpu time=3.78m, real time=2.17m, gc time=113.08s`
 

  • And here are the same calculations run in a fresh 2019 session on the same machine. It is apparent that both time used an memory consumption have been considerably reduced.
 

> L := CodeTools:-Usage(([seq])(Perm(combinat:-randperm(`^`(10, 4))), i = 1 .. 1000)); -1
 

`memory used=77.16MiB, alloc change=59.42MiB, cpu time=1.10s, real time=1.10s, gc time=8.00ms`
 

> CodeTools:-Usage(PermProduct(op(L))); -1
 

`memory used=77.85MiB, alloc change=0 bytes, cpu time=592.00ms, real time=587.00ms, gc time=24.00ms`
 

> CodeTools:-Usage(map(PermOrder, L)); -1
 

`memory used=8.08MiB, alloc change=3.01MiB, cpu time=204.00ms, real time=203.00ms, gc time=0ns`
 

> CodeTools:-Usage(map(PermInverse, L)); -1
 

`memory used=77.30MiB, alloc change=-1.00MiB, cpu time=568.00ms, real time=560.00ms, gc time=16.00ms`
 

> CodeTools:-Usage(map(PermCycleType, L)); -1
 

`memory used=214.05KiB, alloc change=0 bytes, cpu time=124.00ms, real time=125.00ms, gc time=0ns`
 

> CodeTools:-Usage(map(PermPower, L, 3333)); -1
 

`memory used=77.81MiB, alloc change=0 bytes, cpu time=764.00ms, real time=752.00ms, gc time=36.00ms`
 

Real Root Finding 

The RootFinding:-Isolate command has a new algorithm for univariate polynomials that is much faster for ill-conditioned problems and high accuracy solutions.