
KDP_book
.pdf
Mathematica: Functional and procedural programming
for example, a result at the end of the loop. The For-loop allows an arbitrary level of nesting, depending on the size of working area of the software environment. Moreover, in both cases by means of Break[gsv] can not only terminate the loop, but also return the required gsv expression.
In our books [1-3] the reciprocal functional equivalence of both systems is visually illustrated when the most important computing structures of Mathematica with this or that efficiency are simulated by Maple constructions and vice versa. Truly, in principle, it is a quite expected result because built-in languages of both systems are universal and in this regard with one or the other efficiency they can program an arbitrary algorithm. But in the time relation it is not so and at use of the loop structures of a rather large nesting level the Maple can have rather essential advantages before Mathematica. For confirmation we will give a simple example of a loop construction programmed both in the Maple, and the Mathematica system.
The results speak for themselves – if for the Maple 11 the execution of the following for–loop of the nesting 8 requires 7.8 s, the Mathematica 12.1 for execution of the same loop on base of For–function requires already 50.918 s, i.e. approximately 6.5 times more (estimations have been obtained on Dell OptiPlex 3020, i5-4570 3.2 GHz with 64-bit Windows 7 Professional 6.1.7601 service pack 1 Build 7601). In addition, with growth of the nesting depth and range of a loop variable at implementation of the loops this difference rather significantly grows.
> t := time(): for k1 to 10 do for k2 to 10 do for k3 to 10 do for k4 to 10 do for k5 to 10 do for k6 to 10 do for k7 to 10 do for k8 to 10 do 900 end do end do end do end do end do end do end do end do: time() – t; # (Maple 11)
7.800
In[8]= n = 10; t = TimeUsed[]; For[k1 = 1, k1 <= n, k1++,
For[k2 = 1, k2 <= n, k2++, For[k3 = 1, k3 <= n, k3++, For[k4 = 1, k4 <= n, k4++, For[k5 = 1, k5 <= n, k5++, For[k6 = 1, k6 <= n, k6++, For[k7 = 1, k7 <= n, k7++, For[k8 = 1, k8 <= n, k8++, 500]]]]]]]]; TimeUsed[] - t
Out[8]= 50.918
121

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
Our long experience [1-42] of using Maple and Matematica systems of different versions has clearly shown that, in general, programming of loops in the first system is more efficient in the temporal relation.
As another fairly widely used tool in Mathematica for the organization of cyclic calculations is the Do-function, which has the following six coding formats, namely:
Do[E, n] – evaluates an expression E n times;
Do[E, {j, p}] – evaluates E with variable j successively taking on the values 1 through k (in steps of 1);
Do[E, {j, k, p}] – starts with j = k; Do[E, {j, k, p, dt}] – uses steps dt;
Do[E, {j, {k1, k2,…}}] – uses the successive values k1, k2,…;
Do[Exp, {j, j1, j2}, {k, k1, k2},…] – evaluates Exp looping over different values of k etc. for each j.
In the above Do-constructions, there can be both individual expressions and sequences of language sentences as E and Exp (body). To exit the Do loop prematurely or continue it, the body of a loop uses functions Return, Break, Continue; in the case of the nested Do loop, control in such constructions is transferred to the external loop. Examples of Do-loops of the above formats
In[11]:= t := 0; Do[t = t + 1, 1000000]; t
Out[11]= 1000000
In[12]:= t := 0; Do[t = t + k^2, {k, 1000}]; t
Out[12]= 333833500
In[13]:= t := 0; Do[t = t + k^2, {k, 1000, 10000}]; t
Out[13]= 333050501500
In[14]:= t := 0; Do[t = t + k^2, {k, 1000, 10000, 20}]; t
Out[14]= 16700530000
In[15]:= t := 0; Do[t = t + k^2 + j^2 + h^2, {k, 10, 100},
{j, 10, 100}, {h, 10, 100}]; t
Out[15]= 8398548795
In[16]:= A[x_] := Module[{t = 0}, Do[If[t++ > x, Return[t],
Continue[]], Infinity]]; A[900]
Out[16]= 902
122

Mathematica: Functional and procedural programming
In[17]:= A1[x_] := Module[{t = 0}, Do[If[t++ > x, Break[t],
Continue[]], Infinity]]; A1[900]
Out[17]= 902
In[18]:= t = 0; Do[If[t++ > 100, Return[t], Continue[]], 1000]
Out[18]= 102
In[19]:= t = 0; Do[If[t++ > 100, Break[t], Continue[]], 1000]
Out[19]= 102
In[20]:= t := 0; k = 1; Do[t = t + k^2; If[k >= 30, Break[t], Continue[]], {k, 1000}]; {t, k}
Out[20]= {9455, 1}
Note that Break and Return make sense for exit of Do loop both within a procedure containing this loop, and outside it. At the same time, the loop variable is local (see the last example of the previous fragment). Here is a list of several more Mathematica functions for cyclic computing:
While[E, body] – evaluates E, then repetitively evaluates body until E to give True;
In[3338]:= {t, v} = {0, {}}; While[t++; t <= 100, s = Total[AppendTo[v, t]]]; s
Out[3338]= 5050
Nest[F, E, n] – returns the result of application of a function F to an E expression n times;
In[3339]:= Nest[F, (a + b + c), 6]
Out[3339]= F[F[F[F[F[F[a + b + c]]]]]]
FixedPoint[F, E] – starting with E, F is applied repeatedly until two nearby results will identical; in addition FixedPoint[F,E,n] stops after at most n steps. FixedPoint returns the last result it gets.
In[3340]:= FixedPoint[Sqrt, 19.42, 15]
Out[3340]= 1.00009
The FixedPoint1 procedure is a program equivalent of the
FixedPoint based on Do loop:
In[5]:= FixedPoint1[f_, e_, n___] := Module[{a = e, b, p = 1}, Do[b = f @@ {a}; If[SameQ[b, a], Return[], a = b; p++; Continue[]], If[{n} == {}, 10^10, n]]; {p – 1, b}]
In[6]:= FixedPoint1[Sqrt, 19.42, 15]
123

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
Out[6]= {15, 1.00009}
In[7]:= FixedPoint1[Sqrt, 19.42]
Out[7]= {52, 1.}
The procedure call FixedPoint1[f, e, n] returns the list of the form {p, FixedPoint[f, e, n]}, where p is the number of steps of the procedure required to obtain the desired result, whereas n is optional argument similar to n of FixedPoint[f, e, n].
NestWhile[F, E, Test] – starting with E, F is applied repeatedly until applying Test to the result gives False;
In[1119]:= N[NestWhile[Sqrt, 90050, # > 7 &]]
Out[1119]= 4.16208
The NestWhile1 procedure is a program equivalent of the
NestWhile based on Do loop:
In[1132]:= NestWhile1[f_, e_, t_] := Module[{a = e, b, p = 1}, Do[b = f @@ {a}; If[! t @@ {b}, Return[], a = b; p++; Continue[]], Infinity]; {p, b}]
In[1133]:= N[NestWhile1[Sqrt, 90050, # > 7 &]]
Out[1133]= {3., 4.16208}
The procedure call NestWhile1[f, e, t] returns the list of the form {p, NestWhile[f, e, t]}, where p is the number of steps of the procedure required to obtain the desired result, whereas t is the t test analogous to t for NestWhile[f, e, t]. At that, in addition to the presented format the NestWhile has additional five formats, with which the reader can familiarize in the Mathematica help.
TakeWhile[L,t] – returns elements of a list L from the beginning of the list, continuing so long as t for the L elements gives True.
In[1134]:= TakeWhile[{a, b, c, 7, e, r, 15, k, h, m, n, g, s, w},
SymbolQ[#] || PrimeQ[#] &]
Out[1134]= {a, b, c, 7, e, r}
The TakeWhile1 procedure is a program equivalent of the
TakeWhile based on Do loop:
In[1135]:= TakeWhile1[L_List, t_] := Module[{p = {}}, Do[If[t @@ {L[[j]]}, AppendTo[p, L[[j]]], Return[{j, p}]],
{j, Length[L]}]]
124

Mathematica: Functional and procedural programming
In[1136]:= TakeWhile1[{a, b, c, 7, e, r, 15, k, h, m, n, k, h},
SymbolQ[#] || PrimeQ[#] &]
Out[1136]= {7, {a, b, c, 7, e, r}}
The procedure call TakeWhile1[L, T] returns the list of the form {p, TakeWhile[L, T]}, where p is the number of steps of the procedure required to obtain the desired result, whereas T is the test analogous to T in TakeWhile[L, T].
Catch[exp] – returns the argument of the first Throw call that is generated in the evaluation of an exp expression.
In[4906]:= Catch[Do[If[j > 100 && PrimeQ[j], Throw[j]], {j, Infinity}]]
Out[4906]= 101
At that, in addition to the presented format the Catch has additional two formats, with which the reader can familiarize in [15] or in the Mathematica help. The Break, Return, Goto and
Continue functions are used to control whether the loop exits or continues, respectively. Other functions that make substantial use of cyclic computing can be found in the Mathematica help. In addition, most of them have rather simple program analogs using the basic functions Do,For of the loop along with function If of conditional transitions and functions of loop termination control Break, Return, Continue to organize cyclic calculations. Some instructive examples of similar program counterparts are presented above. The above largely applies to both simple and the nested loops whose attachments can alternating and shared different types of loops.
3.3. Special types of cyclic control structures in Mathematica
Along with the basic cyclic structures discussed above, the Mathematica has a number of useful special control structures of cyclic type, which allow to significantly simplify the solution of a number of important tasks. Such structures are realized on the basis of a number of built-in functions Map, MapAt, MapAll, MapIndexed, Select, Sum, Product, etc., allowing to describe the algorithms of mass tasks of processing and calculations in a very
125

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
compact way. In addition, not only good visibility of programs is ensured, but also rather high efficiency of their execution. At the same time, first of all, the tools of the so–called Map group, among which the Map function is the most used, appear to be important. Consider this group a little more detailed.
The main Map function has two formats, namely:
Map[F, exp] or F/@exp – returns the result of applying of F to each element of the first level of an expression exp;
Map[F, exp, levels] – returns the result of applying of F to parts of an expression exp specified by levels; as the values for levels argument can be:
n |
– levels from 1 through n |
Infinity |
– levels from 1 through Infinity |
{n} |
– level n only |
{n1, n2} |
– levels from n1 through n2 |
Here are some examples of management by Map execution:
In[1]:= A[x_, y_] := Module[{t = {}}, Map[If[# <= x,
AppendTo[t, F[#]], Goto[g]] &, Range[y]]; Label[g]; t] In[2]:= A[7, 90]
Out[2]= {F[1], F[2], F[3], F[4], F[5], F[6], F[7]}
In[3]:= A1[x_, y_] := Module[{t = {}}, CheckAbort[Map[
If[# <= x, AppendTo[t, F[#]], Abort[]] &, Range[y]], t]] In[4]:= A1[7, 90]
Out[4]= {F[1], F[2], F[3], F[4], F[5], F[6], F[7]}
In[5]:= Map[g, Map[If[OddQ[#], #, Nothing] &, Range[18]]]
Out[5]= {g[1], g[3], g[5], g[7], g[9], g[11], g[13], g[15], g[17]}
In[6]:= t={}; CheckAbort[Map[If[# <= 7, AppendTo[t, F[#]],
Abort[]] &, Range[90]], t]
Out[6]= {F[1], F[2], F[3], F[4], F[5], F[6], F[7]} In[7]:= Map[j, (a + b)/(c – d)*m*n, Infinity]
Out[7]= j[m]*j[n]*j[j[a] + j[b]]*j[j[j[c] + j[j[–1]*j[d]]]^j[–1]]
MapAll[f, exp] is equivalent to Map[f, exp, {0, Infinity}]. At the same time, the call MapAll[f, exp, Heads –> True] returns the result of applying of f to heads in exp additionally. Whereas the MapIndexed function also have two formats, namely:
126

Mathematica: Functional and procedural programming
MapIndexed[F, exp] – returns the result of applying of F to the elements of an expression exp, giving the part number of each element as the second argument to F;
MapIndexed[F, exp, levels] – returns the result of applying of F to all parts of exp on levels specified by levels.
As a program implementation of the MapIndexed function of the first format can be given:
In[20]:= MapIndexed[F, (a + b)/(c – d) + m*n]
Out[20]= F[(a + b)/(c – d), {1}] + F[m*n, {2}]
In[21]:= MapIndexed1[F_, e_] := Module[{p = 1}, Part[e, 0] @@ Map[F[#, {p++}] &, Op[e]]]
In[22]:= MapIndexed1[F, (a + b)/(c – d) + m*n]
Out[22]= F[(a + b)/(c – d), {1}] + F[m*n, {2}]
The program implementation of the second format of the MapIndexed function we leave to the reader as a useful exercise.
The SubsetMap function has two formats, namely:
SubsetMap[g, j, j1] – returns the result of replacing of elements of a j list by the corresponding elements (whose positions are defined by a list j1) of the list obtained by evaluating g[j].
SubsetMap[g, j, L] – returns the result of replacing of elements jn of an expression j at positions L on g[jn].
Here are some examples of the SubsetMap use:
In[6]:= SubsetMap[Power[#, 3] &, {a, b, c, d, g, h, t}, {1,3,5,7}]
Out[6]= {a^3, b, c^3, d, g^3, h, t^3}
In[7]:= SubsetMap[Power[#, 7] &, {a, b, c, d, g, h, m, t}, 3;;7]
Out[7]= {a, b, c^7, d^7, g^7, h^7, m^7, t}
As a program implementation of the SubsetMap1 function of the first format for case of lists as an argument j can be given:
In[9]:= SubsetMap1[F_, j_, L_] := Map[If[MemberQ[L,
Flatten[Position[j, #]][[1]]], g[#], #] &, j] In[10]:= SubsetMap1[g, {a, b, c, d, g, h, m, t}, {3, 4, 5, 6, 7}]
Out[10]= {a, b, g[c], g[d], g[g], g[h], g[m], t}
The program realization of the more common cases of the SubsetMap function we leave to the reader as a useful exercise.
127

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
Frequently used functions such as Sum, Product, Delete and Select also may be carried to cyclic constructions. Function Sum has five formats of coding from which as an example give the following format:
Sum[F[j], {j, {j1, j2, j3,…}}] – returns the result of summarizing of an expression F[j] using successive values j1, j2, j3,… for j.
Here is function examples use and its program analogue:
In[3336]:= Sum[1/j^2, {j, {1, Infinity}}]
Out[3336]= 1
In[3337]:= Total[Map[1/#^2 &, {1, Infinity}]]
Out[3337]= 1
In[3338]:= Sum[(j + 1)/j^2, {j, {1, m}}]
Out[3338]= 2 + (1 + m)/m^2
In[3339]:= Total[Map[(# + 1)/#^2 &, {1, m}]]
Out[3339]= 2 + (1 + m)/m^2
Function Delete has three formats of coding do not causing any difficulties. Both functions allow multiple levels of nesting. Once again, the functions underlying cyclic constructions allow nesting. Function Select has two formats of coding, namely:
Select[L, test] – returns the list of elements Lj of L list for which test gives True;
Select[L, test, n] – returns the list of the first n elements Lj of L list for which test gives True.
Here is function examples use and its program analogue:
In[4272]:= Select[{a, b, 77, c, 7, d, 14, 5, n}, SymbolQ[#] &&
! SameQ[#, a] || PrimeQ[#] &]
Out[4272]= {b, c, 7, d, 5}
In[4275]:= Select5[L_, test_, n___] := Module[{t},
t = Map[If[test @@ {#}, #, Nothing] &, L]; If[{n} == {}, t, If[Length[t] >= n, t[[1 ;; n]], "Invalid third argument value"]]]
In[4276]:= Select5[{a, b, 77, c, 7, d, 14, 5}, SymbolQ[#] &&
! SameQ[#, a] || PrimeQ[#] &]
Out[4276]= {b, c, 7, d, 5}
In[4277]:= Select5[{a, b, 77, c, 7, d, 14, 5}, SymbolQ[#] &&
! SameQ[#, a] || PrimeQ[#] &, 3]
128

Mathematica: Functional and procedural programming
Out[4277]= {b, c, 7}
In[4285]:= Select5[L_, test_, n___] := {Save["#77#", t],
t = Map[If[test @@ {#}, #, Nothing] &, L], If[{n} == {}, t,
If[Length[t] >= n, t[[1 ;; n]], "Invalid third argument value"]], Get["#77#"], DeleteFile["#77#"]}[[–3]]
In[4286]:= t = 2020; Select5[{a, b, 77, c, 7, d, 14, 5},
SymbolQ[#] && ! SameQ[#, a] || PrimeQ[#] &, 3]
Out[4286]= {b, c, 7} In[4287]:= t Out[4287]= 2020
In[4288]:= Select5[{a, b, 77, c, 7, d, 14, 5}, SymbolQ[#] &&
! SameQ[#, a] || PrimeQ[#] &, 7]
Out[4288]= "Invalid third argument value"
In[8]:= Nest1[F_Symbol, x_, n_Integer] := {Save["#78#", a], a = x, Do[a = F[a], n], a, Get["#78#"], DeleteFile["#78#"]}[[-3]] In[9]:= a = 77; Nest1[G, m + n, 7]
Out[9]= G[G[G[G[G[G[G[m + n]]]]]]]
In[10]:= Nest2[F_List, x_] := {Save["#78#", a], a = x,
Do[a = Reverse[F][[j]][a], {j, Length[F]}], a, Get["#78#"], DeleteFile["#78#"]}[[–3]]
In[11]:= {a, j} = {42, 77}; {Nest2[{F, G, H, S, V}, x], {42, 77}} Out[11]= {F[G[H[S[V[x]]]]], {42, 77}}
The previous fragment also represents program realizations of the built-in Select (Select5) and Nest (Nest1) functions in the form of functions of the list format along with an extension of the Nest (Nest2). The function call Nest2[{a, b, c, d, …}, x] where {a, b, c, d,…} – the list of symbols and x – an expression, returns a[b[c[d[…[x]…]]]]. In these functions, the question of localizing variables by means of built–in Save, Get, DeleteFile functions may be of definite interest. It is shown [6] that for most built–in functions which provide the cyclic structures, it is possible to successfully program their analogues based on system Map, Do and If functions. Because of the importance of the Map function we have created a so-called Map-group consisting of the Map1÷ Map25 means which cover a wide range of applications [6,16].
129

V.Z. Aladjev, M.L. Shishakov, V.A. Vaganov
3.4. Mathematica tools for string expressions
The Mathematica language provides a variety of functions for manipulating strings. Most of these functions are based on a viewing strings as a sequence of characters, and many of these functions are analogous to ones for manipulating lists. Without taking into account the fact that Mathematica has a rather large set of tools for work with string structures, the necessity of tools which are absent in it arises. Some of such tools are represented in the given section; among them are available both simple, and more difficult which appeared in the course of programming of tasks of various purpose as additional procedures and functions and simplifying or facilitating the programming. The section presents a number of tools providing usefulenough operations on strings which supplement and expand the standard system means. These means are widely used at programming of many tools in our package Mathematica, as well as in programming other applications. More fully these tools are presented in [16].
Examples throughout this book illustrate formalization of procedures in the Mathematica that reflects its basic elements and principles, allowing by taking into account the material to directly start creation, at the beginning, of simple procedures of different purpose that are based on processing of string objects. Here only procedures of so–called "system" character intended for processing of string structures are considered that, however, represent also the most direct applied interest for programming of various appendices. Moreover, the procedures and functions that have quite foreseeable volume of source code that allows to carry out their a rather simple analysis are represented here. Their analysis can serve as a rather useful exercise for the reader both who is beginning programming and already having rather serious experience in this direction. Later we will understand under "system" tools the actually built–in tools, and our tools oriented on mass application. In addition it should be noted that string structures are of special interest not only as basic structures with which the system and the user operate, but also as a basis, in particular, of dynamic generation of objects in Mathematica,
130