Functional Programming
in Mathematica
An Introduction
Hossam Karim
ITWorx
FunctionalProgramming-Egypt-2010.nb
About
Work for an Egyptian Software Services Company
Design software for the Bioinformatics and Telecommunications industries
Use Mathematica every day
Implement prototypes and proof of concepts
Design and implement solutions and algorithms
Validate implementations' feasibility, performance and correctness
Code, concepts and algorithms provided in this presentation are not related or affiliated by any means to my employer nor my clients. All the material in this presentations
are samples not suitable for production, and are provided for the sole purpose of demonstration.
FunctionalProgramming-Egypt-2010.nb
The Function
Functions in Mathematics
Function Definition
A Function f is a mapping from the domain X to the co-domain Y and is defined by
f : X Y
The curve y 2 = x 4 - x 2 + 1 can be defined as function by the triple notation
: R, R, : x,
x4 - x2 + 1
> : x R>
(1)
where R is the domain of real numbers and also the co-domain, alternatively,
f : R R, x
x4 - x2 + 1
(2)
A more common notation is
f HxL =
Plotting a Function
Mathematica supports both function and curve plotting
x4 - x2 + 1
(3)
FunctionalProgramming-Egypt-2010.nb
Function plot
In[1]:=
PlotA9
x4 - x2 + 1 , -
x4 - x2 + 1 = , 8x, -3, 3<, PlotRange 3,
AspectRatio 1, PlotStyle 88Black, Thick<<, AxesLabel 8x, y<E
y
3
Out[1]=
x
-3
-2
-1
-1
-2
-3
FunctionalProgramming-Egypt-2010.nb
Curve Plot
ContourPlotAy2 x4 - x2 + 1, 8x, -3, 3<, 8y, -3, 3<,
In[2]:=
Axes True, Frame False, ContourStyle 8Thick<, AxesLabel 8x, y<E
y
3
Out[2]=
x
-3
-2
-1
-1
-2
-3
Functional Programming Languages
Functional Programming Languages has always been the natural choice for implementing computer derived solutions for mathematical
problems including Numerical Analysis, Combinatorics and Algorithms
Haskell
Implementation of the Quick Sort algorithm in Haskell. Demonstrates polymorphic types, pattern matching, list comprehension and
immutability
qsort :: Ord a => [a] -> [a]
qsort []
= []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
where
lesser = [ y | y <- xs, y < p ]
greater = [ y | y <- xs, y >= p ]
Scala
Implementation of the Quick Sort algorithm in Scala. Demonstrates polymorphic types, pattern matching, object-oriented support and partial
functions application
def qsort[T <% Ordered[T]](list:List[T]):List[T] = {
list match {
case Nil Nil
case p::xs
val (lesser,greater) = xs partition (_ <= p)
qsort(lesser) ++ (p :: qsort(greater))
}
}
FunctionalProgramming-Egypt-2010.nb
def qsort[T <% Ordered[T]](list:List[T]):List[T] = {
list match {
case Nil Nil
case p::xs
val (lesser,greater) = xs partition (_ <= p)
qsort(lesser) ++ (p :: qsort(greater))
}
}
Mathematica
Implementation of the Quick Sort algorithm in Mathematica. Demonstrates pattern matching, pattern guards and rule based programming
In[3]:=
ClearAll@qsortD;
qsort@8<D := 8<;
qsort@8p_, xs___<D :=
8Cases@8xs<, y_ ; y <= pD, Cases@8xs<, y_ ; y > pD< .
8lesser_, greater_<
8qsort@lesserD, p, qsort@greaterD< Flatten
In[6]:=
qsort@80, 9, 1, 8, 3, 6, 2, 7, 5, 4<D
Out[6]= 80, 1, 2, 3, 4, 5, 6, 7, 8, 9<
FunctionalProgramming-Egypt-2010.nb
Functions in Mathematica
Numeric Computations
Numeric computations through function calls
Plus@1, Exp@-Times@I , PiDDD
In[210]:=
Out[210]= 0
Or through Mathematical notation
In[8]:=
1 + -
Out[8]= 0
Arbitrary precision
In[9]:=
N@, 100D
Out[9]= 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068
Calculus
Symbolic Calculus
1
In[10]:=
Sin@D
Out[10]= -2 EllipticFA
- , 2E
Accurate results
In[11]:=
% FullSimplify
1
Out[11]=
Sin@D
Algorithms
Optimized algorithms
FunctionalProgramming-Egypt-2010.nb
In[12]:=
Timing@Sort@RandomInteger@81, 10 000 000<, 100 000DDD Short
Out[12]//Short=
80.04, 89, 400, 418, 657, 719, 859, 947, 1057, 1061, 99 982,
9 998 951, 9 998 953, 9 999 009, 9 999 077, 9 999 123, 9 999 227, 9 999 236, 9 999 314, 9 999 497<<
Algorithm analysis
2n
In[13]:=
T@nD . RSolveA9T@nD TA
E + 1, T@1D 1=, T@nD, nE
3
Log@nD
Out[13]= 91 +
=
3
LogA E
2
Graphics
Stunning graphics
In[236]:=
HParametricPlot3D@ 8Cos@ D Sin@D, Sin@D Sin@D, Cos@D<, 8, 0, 2 <,
8, 0, <, PlotPoints 100, Mesh None, ColorFunction H8x, y, z, , < Hue@DL,
ColorFunctionScaling False, Boxed False, Axes FalseD Magnify@, .5D &L &
9Sin@D Cos@D, Sin@D Cos@D, Sin@ + D Cos@ + D, , , + =
Partition@, 3D & Grid
Out[236]=
FunctionalProgramming-Egypt-2010.nb
Define Your Own Function
A Function as a Rule
Functions can be defined as a delayed assignment rule
In[15]:=
f@x_D :=
x3 - x + 1
Functions can accept multiple parameters
In[16]:=
f@x_, a_, b_D :=
x3 + a x + b
10
FunctionalProgramming-Egypt-2010.nb
Calling a Function
Default Form
Default Form, notice the square brackets
In[17]:=
f@2D
Out[17]=
Prefix Form
Prefix Form, using the @ sign
In[18]:=
f2
Out[18]=
Postfix Form
Postfix Form, using the // sign
In[19]:=
2 Sin
Out[19]= 0
Infix Form
Infix Form, function surrounded by ~ sign
In[20]:=
81, 2, 3< ~ Join ~ 84, 5, 6<
Out[20]= 81, 2, 3, 4, 5, 6<
Multiple Arguments
Function call with multiple actual arguments
FunctionalProgramming-Egypt-2010.nb
In[223]:=
Magnify@ChemicalData@"Ethanol", "MoleculePlot"D, 1D
Out[223]=
11
12
FunctionalProgramming-Egypt-2010.nb
Domains and Patterns
Domains as Patterns
Domains can be specified as patterns
In[22]:=
ClearAll@squareD;
square@i_IntegerD := i2
square@i_RealD := Floor@iD2
square@i_ComplexD := Re@iD2
square@a_SymbolD := a2
square@SomeDataType@a_DD := a2
In[28]:=
[email protected], square@2D, square@2 + 3 D, square@xD, square@SomeDataType@xDD<
2
2
Out[28]= 94, 4, 4, x , x =
Patterns and Lists
Expressive patterns on lists, notice how ordering is important
One or more
__
Zero or more
In[29]:=
In[34]:=
ClearAll@listOpD;
listOp@8<D := 8<
listOp@8x_, y_<D := 8y, x<
listOp@8x_, xs__<D := 8xs<
listOp@l : 88__< ...<D := Reverse@lD
___
H* flip a tuple *L
H* drop the first element *L
H* match a list of lists *L
8listOp@81, 2, 3<D, listOp@81, 2<D, listOp@8 81, 2<, 83, 4< <D <
Out[34]= 882, 3<, 82, 1<, 883, 4<, 81, 2<<<
FunctionalProgramming-Egypt-2010.nb
Guards on Patterns
Guards on Domains
Guards can be specified using the Pattern ? Predicate notation
In[35]:=
ClearAll@collatzD;
collatz@n_Integer ? EvenQD := n 2 H* Matches only even integers *L
collatz@n_IntegerD := 3 n + 1 H* Matches all integers *L
In[38]:=
8collatz@3D, collatz@4D<
Out[38]= 810, 2<
Arbitrary Conditions
A condition can be specified on a pattern using Pattern /; Predicate notation
Example : Bubble Sort
By Dr Jon D Harrop, 2010 (Modified)
Using pattern matching and conditions on patterns, bubble sort can then be defines as
In[39]:=
bubbleSort@8xs___, x_, y_, ys___<D := bubbleSort@8xs, y, x, ys<D ; x y
For example
In[40]:=
bubbleSort@83, 2, 1<D
Out[40]= bubbleSort@81, 2, 3<D
We can simply extract the sorted list using the rule
In[211]:=
bubbleSort@83, 2, 1<D . _@sorted_D sorted
Out[211]= 81, 2, 3<
13
14
FunctionalProgramming-Egypt-2010.nb
Pure Functions
Defining a Pure Function
The Notation
A function that squares its argument
In[41]:=
x x2
2
Out[41]= FunctionAx, x E
Square function applied at 3
In[42]:=
Ix x2 M@3D
Out[42]= 9
A function with a list as its argument
In[43]:=
8x, y<
x2 + y2
@3, 4D
Out[43]= 5
The (# &) Notation
The notation is programmatically equivalent to the notation
Square function applied at 3
In[44]:=
2 &@3D
Out[44]= 9
A pure function with 2 arguments, notice the numbering after #
In[45]:=
Out[45]= 5
12 + 22 &@3, 4D
FunctionalProgramming-Egypt-2010.nb
Higher-Order Functions
Map
Map as a function call
In[46]:=
MapAx x2 , 8a, b, c, d<E
2
2
2
2
Out[46]= 9a , b , c , d =
Using the ( /@ ) Notation
In[47]:=
Ix x2 M 8a, b, c, d<
2
2
2
2
Out[47]= 9a , b , c , d =
The mapped function can be composed of any type of expression
In[48]:=
8Mean@D, Variance@D, PDF@, xD< &
8NormalDistribution@, D, MaxwellDistribution@D, GammaDistribution@, D<
x2
Hx-L2
2 2
H-8 + 3 L 2
Out[48]= 99, ,
x2
x-1+ -
=, 92
2 2
=, 9 , ,
==
Gamma@D
Or a composed function
In[215]:=
HChemicalData@"Caffeine", D Magnify@, .5D &L & 8
"CHColorStructureDiagram", "CHStructureDiagram", "ColorStructureDiagram", "StructureDiagram",
"MoleculePlot", "SpaceFillingMoleculePlot"< Partition@, 3D & Grid@, Frame AllD &
H
O
C
H
H
O
C
N
N
H
N
N
Or used inside a manipulation
N
N
C
H
O
Out[215]=
C
H
C
O
O
H
15
16
FunctionalProgramming-Egypt-2010.nb
Or used inside a manipulation
In[50]:=
ClearAll@tux, browsersD;
8tux, browsers< = 9
, 9
==;
Manipulate@
Map@
ImageCompose@tux, ImageResize@, Scaled@scaleDD, 8horizontal, vertical<D &, browsers
D GraphicsRow,
8scale, 0.5, 1<,
8horizontal, 60, 200, 10<,
8vertical, 60, 200, 10<
D
scale
horizontal
vertical
Out[52]=
Select
In[53]:=
Select@8-1, 3, -2, 5, 0<, n 0 < nD
Out[53]= 83, 5<
Fold
In[54]:=
Fold@8x, y< x + y, 0, 8a, b, c, d<D
Out[54]= a + b + c + d
Folding to the left or to the right
FunctionalProgramming-Egypt-2010.nb
In[218]:=
Manipulate@
8
Fold@F@1, 2D &, x, Take@8a,
TreeForm@, AspectRatio
Fold@F@2, 1D &, x, Take@8a,
TreeForm@, AspectRatio
< GraphicsRow Magnify@,
8step, 0, 4, 1<
D
b, c, d<, stepDD
1.2, PlotLabel
b, c, d<, stepDD
1.2, PlotLabel
1D &,
"Fold Left"D &,
"Fold Right"D &
step
Fold Left
Fold Right
F
Out[218]=
Power Set
In[56]:=
Fold@8set, element< set H ~ Append ~ element & setL, 88<<, 8, , <D
Out[56]= 88<, 8<, 8<, 8<, 8, <, 8, <, 8, <, 8, , <<
One more time
In[57]:=
FoldList@8set, element< set H ~ Append ~ element & setL, 88<<, 8, , <D Column
88<<
88<, 8<<
Out[57]= 88<, 8<, 8<, 8, <<
88<, 8<, 8<, 8<, 8, <, 8, <, 8, <, 8, , <<
NestWhileList
In[58]:=
NestWhileListAx
, 32, i i 1E
2
Out[58]= 832, 16, 8, 4, 2, 1<
Pascal Triangle
Pascal triangle can be defined using binomials
17
18
FunctionalProgramming-Egypt-2010.nb
In[59]:=
Table@Binomial@n, kD, 8n, 0, 4<, 8k, 0, n<D Column@, CenterD &
81<
81, 1<
81, 2, 1<
Out[59]=
81, 3, 3, 1<
81, 4, 6, 4, 1<
This can defined using the pattern
In[60]:=
tuples@8<
8x_<D := 8<
tuples@8x_, y_, ys___<D := 8x + y< ~ Join ~ tuples@8y, ys<D
pascal@h_D := NestWhileList@81< ~ Join ~ tuples@D ~ Join ~ 81< &, 81<, Length@D < h &D
pascal@9D Column@, CenterD &
81<
81, 1<
81, 2, 1<
81, 3, 3, 1<
81, 4, 6, 4, 1<
Out[63]=
81, 5, 10, 10, 5, 1<
81, 6, 15, 20, 15, 6, 1<
81, 7, 21, 35, 35, 21, 7, 1<
81, 8, 28, 56, 70, 56, 28, 8, 1<
And nicely manipulated,
In[64]:=
ClearAll@hexagon, renderD;
2k
hexagon@x_, y_D := PolygonATableA9SinA
2k
E + x, CosA
E + y=, 8k, 6<EE
6
Length@lD
render@l_ListD := GraphicsA9HueA
E, hexagon@0, 0D, Text@Style@, White, Bold, 10 DD=E & l
GraphicsRow@, ImageSize 850 * Length@D, 30<, Spacings 82, 0<D &
Manipulate@
Graphics@Hrender@D & pascal@hDL GraphicsColumn@, Alignment Center, Spacings 80, -8<D &D
Magnify@, 1.5D &,
8h, 1, 5, 1<
D
1
1
Out[67]=
1
1
1
3 n + 1 Problem
2
3
1
3
1
4
FunctionalProgramming-Egypt-2010.nb
3 n + 1 Problem
In[68]:=
n2
EvenQ@nD
3 n + 1 OddQ@nD
NestWhileList@collatz, 200, m m 1D
collatz := n
Out[69]= 8200, 100, 50, 25, 76, 38, 19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1<
In[70]:=
Manipulate@
MapIndexed@
Text@Style@1, Blue, Italic, 45 - 2DD &, NestWhileList@collatz, x, m m != 1DD,
8x, 10, 100, 10<
D
Out[70]=
70 35 106 53 160
80 40 20 10 5 16 8 4 2 1
,
19
20
FunctionalProgramming-Egypt-2010.nb
Example: Binary Search Tree
Haskell
Haskell approach to Algebraic Data Types and Pattern Matching
data Tree a =
Empty | Node (Tree a) a (Tree a) deriving(Show, Eq)
insert :: Ord a => a -> Tree a -> Tree a
insert n Empty = Node Empty n Empty
insert n (Node left x right)
| n < x
= Node (insert n left) x right
| otherwise = Node left x (insert n right)
inorder :: Ord a => Tree a -> [a]
inorder Empty = []
inorder (Node left x right) =
inorder left ++ [x] ++ inorder right
bst :: Ord a => [a] -> Tree a
bst [] = Empty
bst (x : xs) = foldr(insert) (insert x Empty) xs
Mathematica
The same algorithm in Mathematica syntax
In[71]:=
ClearAll@tree, insert, inorder, bstD;
tree = nil
node@_, _, _D;
insert@n_, nilD := node@nil, n, nilD;
insert@n_, node@l_, x_, r_DD ; n < x := node@Hinsert@n , lDL , x , rD;
insert@n_, node@l_, x_, r_DD := node@l, x, Hinsert@n, rDLD;
inorder@nilD := 8<;
inorder@node@l_, x_, r_DD := inorder@lD ~ Join ~ 8x< ~ Join ~ inorder@rD;
bst@8<D := nil
bst@8x_, xs___<D := Fold@insert@2, 1D & , insert@x, nilD, 8xs<D;
In[80]:=
inorder bst@88, 3, 10, 1, 6, 9, 12, 4, 7, 13, 11<D
Out[80]= 81, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13<
Visualizing a Binary Search Tree
In order to be able to visualize a BST, we need to convert the tree of nodes into a {src dst, ...} representation. Using our structure, the
binary search tree of the list {8, 3, 10, 1, 6} is
In[81]:=
bst@88, 3, 10, 1, 6<D
Out[81]= node@node@node@nil, 1, nilD, 3, node@nil, 6, nilDD, 8, node@nil, 10, nilDD
We can then define
FunctionalProgramming-Egypt-2010.nb
In[82]:=
ClearAll@tupleD;
tuple@nilD := 8<
tuple@node@nil, x_, nilDD := 8<
tuple@node@l : node@_, a_, _D, x_, nilDD := tuple@lD ~ Join ~ 8x a<
tuple@node@nil, x_, r : node@_, b_, _DDD := 8x b< ~ Join ~ tuple@rD
tuple@node@l : node@_, a_, _D, x_, r : node@_, b_, _DDD :=
tuple@lD ~ Join ~ 8x a, x b< ~ Join ~ tuple@rD
Then
In[88]:=
tuple@bst@88, 3, 10, 1, 6, 9, 12, 4, 7, 13, 11<DD
Out[88]= 83 1, 3 6, 6 4, 6 7, 8 3, 8 10, 10 9, 10 12, 12 11, 12 13<
Plotting the BST
In[89]:=
TreePlot@tuple@bst@88, 3, 10, 1, 0, 4, 6, 5, 9, 12, 2, 7, 13, 11<DD,
Automatic, 8, VertexLabeling True, DirectedEdges True,
PlotLabel "88,3,10,1,0,4,6,5,9,12,2,7,13,11<", VertexRenderingFunction
H8ps, v< 8White, EdgeForm@8Black, Thick<D, Disk@ps, .2D, Black, Text@v, psD<LD
88,3,10,1,0,4,6,5,9,12,2,7,13,11<
Out[89]=
10
12
11
We can then visualize a random BST construction step by step
13
21
22
FunctionalProgramming-Egypt-2010.nb
In[214]:=
With@8l = RandomInteger@81, 100<, 10D DeleteDuplicates<,
Manipulate@
8
Text@Style@Framed@lD, 12, Bold, Black DD,
TreePlot@
tuple bst Take@l, stepD,
Automatic, l@@1DD, VertexLabeling True, DirectedEdges True, VertexRenderingFunction
H8ps, v< 8White, EdgeForm@8Black, Thick<D, Disk@ps, .2D, Black, Text@v, psD<L,
ImageSize 8400, 300<, ImagePadding 1
D,
Text@Style@Framed@inorder bst Take@l, stepDD, 12, Bold, BlueDD
< Column@, CenterD &,
8step, 2, Length@lD, 1<
D
D
step
891, 57, 43, 99, 92, 50, 11, 48, 89<
91
57
99
43
92
Out[214]=
11
50
48
811, 43, 48, 50, 57, 91, 92, 99<
FunctionalProgramming-Egypt-2010.nb
Pattern Matching and Transformation
Matching Cases
Match Cases
In[91]:=
CasesA9a2 , b3 , c4 , d5 , e6 =, _2 E
2
Out[91]= 9a =
Match Cases with a predicate
In[92]:=
CasesA9a2 , b3 , c4 , d5 , e6 =, _n_ ; EvenQ@nDE
2
4
6
Out[92]= 9a , c , e =
Match Cases with a predicate and a transformation rule
In[93]:=
CasesA9a2 , b3 , c4 , d5 , e6 =, x_n_ ; OddQ@nD xn+1 E
4
6
Out[93]= 9b , d =
Pattern Matching and Rules
Swap is simple
In[94]:=
8a, b< . 8x_, y_< 8y, x<
Out[94]= 8b, a<
Decompose an expression
In[95]:=
x Sin@D - y Cos@D . Ha_ Sin@_D - b_ Cos@_DL 8a, b, <
Out[95]= 8x, y, <
Match rules
23
24
FunctionalProgramming-Egypt-2010.nb
In[96]:=
ClearAll@gD;
g = 8
,
i,
a,
<;
GraphPlot@g,
,
j,
b
VertexLabeling True, AspectRatio 0.2D Magnify@, 1.5D &
Out[98]=
Use delayed rules
In[99]:=
H* find the children of the vertex in the Graph g *L
. 8 H x_L 8x< , _ 8< < & g Flatten
Out[99]= 8a, b<
Example: Palindrome
Generate a sequence of probable palindrome integers
In[100]:=
alg196@n_IntegerD := n + HIntegerDigits@nD Reverse FromDigitsL
NestWhileList@alg196, 77, < 10 000 000 &D
Out[101]= 877, 154, 605, 1111, 2222, 4444, 8888, 17 776, 85 547, 160 105, 661 166, 1 322 332, 3 654 563, 7 309 126, 13 528 163<
Recursively test if a sequence is a palindrome
In[102]:=
isPalindrome@seq_ListD := seq . 8
8<
8x_< True,
8x_, xs___, y_< x == y && isPalindrome@8xs<D
<
Test the sequence
In[103]:=
Select@NestWhileList@alg196, 77, < 10 000 000 &D, isPalindrome@IntegerDigits@DD &D
Out[103]= 877, 1111, 2222, 4444, 8888, 661 166, 3 654 563<
Example: Run Length Encoding
Perform run length encoding on a finite sequence
By Frank Zizza, 1990
Use replace repeated (//.)
FunctionalProgramming-Egypt-2010.nb
In[104]:=
runLengthEncoding@l_ListD := Map@8, 1< &, lD .
8head___, 8x_, n_<, 8x_, m_<, tail___< 8head, 8x, n + m<, tail<
In[105]:=
runLengthEncoding@8a, a, a, b, b, c, c, c, c, a, a<D
Out[105]= 88a, 3<, 8b, 2<, 8c, 4<, 8a, 2<<
How does the magic happen?
First define the magical rule
In[106]:=
ClearAll@ruleD;
rule = 8head___, 8x_, n_<, 8x_, m_<, tail___< 8head, 8x, n + m<, tail<;
Second, generate a list tuples of the form 88e1 , 1<, 8e2 , 1<, ..., 8en , 1<<
In[108]:=
Map@8, 1< &, 8a, a, a, b, b, c, c, c<D
Out[108]= 88a, 1<, 8a, 1<, 8a, 1<, 8b, 1<, 8b, 1<, 8c, 1<, 8c, 1<, 8c, 1<<
Keep applying the transformation until the input is exhausted
In[109]:=
% . rule
Out[109]= 88a, 2<, 8a, 1<, 8b, 1<, 8b, 1<, 8c, 1<, 8c, 1<, 8c, 1<<
25
26
FunctionalProgramming-Egypt-2010.nb
Example: Mathematica in Bioinformatics
XML in Mathematica
Mathematica supports a large variety of data formats, XML happens to be one of them
In[225]:=
xml = Import@"~workpresentationMathematica-Conference-2010codexmlgraph.xml", "XML"D
Out[225]= XMLObject@DocumentD@8<,
XMLElement@v, 8id root<, 8XMLElement@v, 8id a<, 8XMLElement@v, 8id a1, cost 1<, 8<D,
XMLElement@v, 8id a2, cost 2<, 8<D, XMLElement@v, 8id a3, cost 3<, 8<D<D,
XMLElement@v, 8id b<, 8XMLElement@v, 8id b1, cost 4<, 8<D, XMLElement@v, 8id b2, cost 5<, 8<D,
XMLElement@v, 8id b3, cost 6<, 8<D<D, XMLElement@v, 8id c<, 8XMLElement@v, 8id c1, cost 7<, 8<D,
XMLElement@v, 8id c2, cost 8<, 8<D, XMLElement@v, 8id c3, cost 9<, 8<D<D<D, 8<D
The XML document represents a graph, each vertex v is represented as an element. Children of an element are connected to the parent, the
hierarchy represents the edges. The following functions use Mathematica XML support to create a garph representation of the XML document and plot it
In[226]:=
ClearAll@root, id, cost, recD;
root@XMLObject@_D@_, r_, _DD := r
id@XMLElement@_, as_, 8___<DD := "id" . as
cost@XMLElement@_, 8as__<, 8___<DD := "cost" . 8as, _ "0"<
rec@e : XMLElement@"v", _, cs : 8___<DD :=
H8id e id , cost < & HcsLL ~ Join ~ Hrec cs Flatten@, 1D &L
Recursively walk the element structure and create a Mathematica graph representation
In[231]:=
rec@root@xmlDD
Out[231]= 88root a, 0<, 8root b, 0<, 8root c, 0<, 8a a1, 1<, 8a a2, 2<,
8a a3, 3<, 8b b1, 4<, 8b b2, 5<, 8b b3, 6<, 8c c1, 7<, 8c c2, 8<, 8c c3, 9<<
Plot the extracted graph
FunctionalProgramming-Egypt-2010.nb
In[232]:=
27
rec@root@xmlDD GraphPlot@, VertexLabeling True, EdgeLabeling TrueD & Magnify@, 1D &
a1
c3
a2
c2
2
8
a
c
0
0
7
root
Out[232]=
a3
c1
0
b
4
b1
6
5
b3
b2
Sequence Alignment
In[118]:=
xml = Import@"~workpresentationMathematica-Conference-2010codexmlsequenceML.xml", "XML"D;
In[119]:=
ClearAll@root, sequenceList, sequence, elementD;
root@XMLObject@_D@_, r_, _DD := r
sequenceList@XMLElement@"sequenceML", _, seqs_DD := sequence seqs
sequence@e : XMLElement@"sequence", 8"seqID" id_<, cs_DD :=
8
seqID id,
name element@"name", csD,
description element@"description", csD,
aminoAcidSequence element@"aminoAcidSequence", csD
<
element@name_, elements_D :=
Cases@elements, HXMLElement@n_, 8<, 8value_<D ; n === name valueLD First
In[124]:=
root@xmlD sequenceList First
Out[124]= 8seqID gi58374180gbAAW72226.1, name HA,
description Influenza A virus HAduckShandong0932004HH5N1LL, aminoAcidSequence
MEEIVLLLAIVSLVKSDQICIGYHANNSTEQVDTIMEKNVTVTHAQDILEKTHNGKLCDLDGVKPLILRDCSVAGWLLGNPMCDEFINVPEWSYIVEKANPAND
LCYPGDFNDYEELKHLLSRINHFEKIQIIPKSSWSDHEASSGVSSACPYNGKSSFFRNVVWLIKKNSSYPTIKRSYNNTNQEDLLILWGIHHPNDAAE
QTKLYQNPTTYISVGTSTLNQRLVPKIATRSKVNGQSGRMEFFWTILKPNDAINFESNGNFIAPEYAYKIVKKGDSAIMKSELEYGNCNTKCQTPMGA
INSSMPFHNIHPLTIGECPKYVKSNRLVLATGLRNTPQRERRRKKRGLFGAIAGFIEGGWQGMVDGWYGYHHSNEQGSGYAADKESTQKAIDGVTNKV
NSIIDKMNTQFEAVGREFNNLERRIENLNKKMEDGFLDVWTYNAELLVLMENERTLDFHDSNVKNLYDKVRLQLRDNAKELGNGCFEFYHKCDNECME
SVKNGTYDYPRYSEEARLNREEISGVKLESMGTYQILSIYSTVASSLALAIMVAGLSLWMCSNGSLQCRICI<
28
FunctionalProgramming-Egypt-2010.nb
In[125]:=
8first, last< = Hroot@xmlD sequenceListL . 8x_, ___, y_< 8x, y<
Out[125]= 88seqID gi58374180gbAAW72226.1, name HA,
description Influenza A virus HAduckShandong0932004HH5N1LL, aminoAcidSequence
MEEIVLLLAIVSLVKSDQICIGYHANNSTEQVDTIMEKNVTVTHAQDILEKTHNGKLCDLDGVKPLILRDCSVAGWLLGNPMCDEFINVPEWSYIVEKANPA
NDLCYPGDFNDYEELKHLLSRINHFEKIQIIPKSSWSDHEASSGVSSACPYNGKSSFFRNVVWLIKKNSSYPTIKRSYNNTNQEDLLILWGIHHPN
DAAEQTKLYQNPTTYISVGTSTLNQRLVPKIATRSKVNGQSGRMEFFWTILKPNDAINFESNGNFIAPEYAYKIVKKGDSAIMKSELEYGNCNTKC
QTPMGAINSSMPFHNIHPLTIGECPKYVKSNRLVLATGLRNTPQRERRRKKRGLFGAIAGFIEGGWQGMVDGWYGYHHSNEQGSGYAADKESTQKA
IDGVTNKVNSIIDKMNTQFEAVGREFNNLERRIENLNKKMEDGFLDVWTYNAELLVLMENERTLDFHDSNVKNLYDKVRLQLRDNAKELGNGCFEF
YHKCDNECMESVKNGTYDYPRYSEEARLNREEISGVKLESMGTYQILSIYSTVASSLALAIMVAGLSLWMCSNGSLQCRICI<,
8seqID gi108671045gbABF93441.1, name hemagglutinin,
description Influenza A virus HSt Jude H5N1 influenza seed virus 163222L, aminoAcidSequence
MEKIVLLLAIVSLVKSDQICIGYHANNSTEQVDTIMEKNVTVTHAQDILEKTHNGKLCDLDGVKPLILRDCSVAGWLLGNPMCDEFLNVPEWSYIVEKINPA
NDLCYPGNFNDYEELKHLLSRINHFEKIQIIPKSSWSDHEASSGVSSACPYQGRSSFFRNVVWLIKKNNAYPTIKRSYNNTNQEDLLVLWGIHHPN
DAAEQTRLYQNPTTYISVGTSTLNQRLVPKIATRSKVNGQSGRMEFFWTILKPNDAINFESNGNFIAPENAYKIVKKGDSTIMKSELEYGNCNTKC
QTPIGAINSSMPFHNIHPLTIGECPKYVKSNRLVLATGLRNSPQIETRGLFGAIAGFIEGGWQGMVDGWYGYHHSNEQGSGYAADKESTQKAIDGV
TNKVNSIIDKMNTQFEAVGREFNNLERRIENLNKKMEDGFLDVWTYNAELLVLMENERTLDFHDSNVKNLYDKVRLQLRDNAKELGNGCFEFYHRC
DNECMESVRNGTYDYPQYSEEARLKREEISGVKLESIGTYQILSIYSTVASSLALAIMVAGLSLWMCSNGSLQCRICI<<
In[126]:=
SequenceAlignment@aminoAcidSequence . first, aminoAcidSequence . lastD
Out[126]= 8ME, 8E, K<, IVLLLAIVSLVKSDQICIGYHANNSTEQVDTIMEKNVTVTHAQDILEKTHNGKLCDLDGVKPLILRDCSVAGWLLGNPMCDEF,
8I, L<, NVPEWSYIVEK, 8A, I<, NPANDLCYPG, 8D, N<, FNDYEELKHLLSRINHFEKIQIIPKSSWSDHEASSGVSSACPY,
8N, Q<, G, 8K, R<, SSFFRNVVWLIKKN, 8SS, NA<, YPTIKRSYNNTNQEDLL, 8I, V<, LWGIHHPNDAAEQT, 8K, R<,
LYQNPTTYISVGTSTLNQRLVPKIATRSKVNGQSGRMEFFWTILKPNDAINFESNGNFIAPE, 8Y, N<, AYKIVKKGDS, 8A, T<,
IMKSELEYGNCNTKCQTP, 8M, I<, GAINSSMPFHNIHPLTIGECPKYVKSNRLVLATGLRN, 8T, S<, PQ, 8R, I<, E, 8RRRKK, T<,
RGLFGAIAGFIEGGWQGMVDGWYGYHHSNEQGSGYAADKESTQKAIDGVTNKVNSIIDKMNTQFEAVGREFNNLERRIENLNKKMEDGFLDVWTYNAELLVLMEN
ERTLDFHDSNVKNLYDKVRLQLRDNAKELGNGCFEFYH, 8K, R<, CDNECMESV, 8K, R<, NGTYDYP,
8R, Q<, YSEEARL, 8N, K<, REEISGVKLES, 8M, I<, GTYQILSIYSTVASSLALAIMVAGLSLWMCSNGSLQCRICI<
FunctionalProgramming-Egypt-2010.nb
Example: Mathematica XQuery
XQuery
A fluent XML Query Language from W3C
XQuery FLWOR Expression
An XQuery expression is typically a for, let, where, order by and return construct
for $x in doc("books.xml")/bookstore/book
where $x/price>30
order by $x/title
return $x/title
XML in Mathematica
Mathematica XML Support
Import the XML document
In[127]:=
xml = Import@"~workpresentationMathematica-Conference-2010xmlbooks.xml", "XML"D
Out[127]= XMLObject@DocumentD@8XMLObject@DeclarationD@Version 1.0, Encoding ISO-8859-1D<,
XMLElement@bookstore, 8<, 8XMLElement@book, 8category COOKING<,
8XMLElement@title, 8lang en<, 8Everyday Italian<D, XMLElement@author, 8<, 8Giada De Laurentiis<D,
XMLElement@year, 8<, 82005<D, XMLElement@price, 8<, 830.00<D<D,
XMLElement@book, 8category CHILDREN<, 8XMLElement@title, 8lang en<, 8Harry Potter<D,
XMLElement@author, 8<, 8J K. Rowling<D, XMLElement@year, 8<, 82005<D, XMLElement@price, 8<, 829.99<D<D,
XMLElement@book, 8category WEB<, 8XMLElement@title, 8lang en<, 8XQuery Kick Start<D,
XMLElement@author, 8<, 8James McGovern<D, XMLElement@author, 8<, 8Per Bothner<D,
XMLElement@author, 8<, 8Kurt Cagle<D, XMLElement@author, 8<, 8James Linn<D, XMLElement@author,
8<, 8Vaidyanathan Nagarajan<D, XMLElement@year, 8<, 82003<D, XMLElement@price, 8<, 849.99<D<D,
XMLElement@book, 8category WEB<, 8XMLElement@title, 8lang en<, 8Learning XML<D, XMLElement@
author, 8<, 8Erik T. Ray<D, XMLElement@year, 8<, 82003<D, XMLElement@price, 8<, 839.95<D<D<D, 8<D
XQuery like DSL in Mathematica
Define an XQuery like Domain Specific Language (DSL) for XML processing using Mathematica's Functional approach
The tiny language is a set of higher - order functions, each function returns a function that can act on the XML axis
29
30
FunctionalProgramming-Egypt-2010.nb
In[128]:=
ClearAll@doc, where, orderBy, e, att, attribute, data, returnD;
doc@XMLObject@DocumentD@_, root_, _DD := root;
where = Select;
orderBy = Sort;
e@n_StringD := es Cases@es, XMLElement@n , _, _D, D;
att@XMLElement@_ , rules_, _D, n_StringD := Hn . Hrules ~ Join ~ 8_ <LL;
attribute@XMLElement@_ , rules_, _D, n_StringD := 8n Hn . rulesL<;
attribute@ n_StringD := es attribute@, nD & es;
attribute@ n_String, pred_D := el pred@att@el, nDD;
data@n_StringD := es Cases@es, XMLElement@n , _, 8d_<D d, D;
data@n_String, pred_D := es HCases@es, XMLElement@n , _, 8d_<D ; pred@dD, D != 8<L;
return@es_, f_D := f es;
Mathematica XQuery DSL in Action
XPath Expressions
All book titles
In[140]:=
doc@xmlD e@"book"D data@"title"D
Out[140]= 8Everyday Italian, Harry Potter, XQuery Kick Start, Learning XML<
All book authors
In[141]:=
doc@xmlD e@"book"D data@"author"D
Out[141]= 8Giada De Laurentiis, J K. Rowling, James McGovern,
Per Bothner, Kurt Cagle, James Linn, Vaidyanathan Nagarajan, Erik T. Ray<
The return function
Return a { {author..} title} tuple
In[142]:=
Hdoc@xmlD e@"book"DL ~
return ~ Hbs
HHdata@"author"D@D . 8a_< aL Hdata@"title"D@D . 8t_< tLL & bs
L
Out[142]= 8Giada De Laurentiis Everyday Italian, J K. Rowling Harry Potter,
8James McGovern, Per Bothner, Kurt Cagle, James Linn, Vaidyanathan Nagarajan< XQuery Kick Start,
Erik T. Ray Learning XML<
The where function
All titles with price > 30
In[143]:=
Hdoc@xmlD e@"book"DL ~
where ~ Hb b data@"price", ToExpression@D > 30 &DL ~
return ~ data@"title"D
Out[143]= 8XQuery Kick Start, Learning XML<
All titles in the COOKING category
FunctionalProgramming-Egypt-2010.nb
In[144]:=
Hdoc@xmlD e@"book"DL ~
where ~ Hb b attribute@"category", == "COOKING" &DL ~
return ~ data@"title"D
Out[144]= 8Everyday Italian<
All titles in the WEB category with price > 40
In[145]:=
Hdoc@xmlD e@"book"DL ~
where ~ Hb H
Hb data@"price", ToExpression@D > 40 &DL && Hb attribute@"category", == "WEB" &DL
L L~
return ~ data@"title"D
Out[145]= 8XQuery Kick Start<
The order by function
Order by title in descending order
In[146]:=
Hdoc@xmlD e@"book"DL ~
where ~ Hb b attribute@"category", == "WEB" &DL ~
orderBy ~ HOrder@1 data@"title"D, 2 data@"title"DD < 0 &L ~
return ~ data@"title"D
Out[146]= 8XQuery Kick Start, Learning XML<
All books in WEB category, ordered by title in ascending order, formatted as { title price } list
In[147]:=
Hdoc@xmlD e@"book"DL ~
where ~ Hb b attribute@"category", == "WEB" &DL ~
orderBy ~ HOrder@1 data@"title"D, 2 data@"title"DD > 0 &L ~
return ~ Hbs
HHdata@"title"D@D . 8t_< tL Hdata@"price"D@D . 8p_< pLL & bs
L
Out[147]= 8Learning XML 39.95, XQuery Kick Start 49.99<
31
32
FunctionalProgramming-Egypt-2010.nb
Example: SQL
Establish a Database Connection
H* HSQL memory db *L
Needs@"DatabaseLink`"D
bookstore = OpenSQLConnection@D;
In[148]:=
Create the Book table
SQLDropTable@bookstore, D & SQLTableNames@bookstoreD;
SQLCreateTable@bookstore, SQLTable@"BOOK"D, 8
SQLColumn@"ID", "DataTypeName" "INTEGER"D,
SQLColumn@"TITLE", "DataTypeName" "VARCHAR", "DataLength" 128D,
SQLColumn@"YEAR", "DataTypeName" "VARCHAR", "DataLength" 4D,
SQLColumn@"PRICE", "DataTypeName" "FLOAT"D
<D;
SQLTableNames@bookstoreD
In[150]:=
Out[152]= 8BOOK<
Load books from XML
ClearAll@booksD;
books =
Hdoc@xmlD e@"book"DL ~ return ~
Hbs
8
data@"title"D@D . 8t_< t,
data@"year"D@D . 8y_< y,
data@"price"D@D . 8p_< p
In[153]:=
< & bsL
Out[154]= 88Everyday Italian, 2005, 30.00<, 8Harry Potter, 2005, 29.99<,
8XQuery Kick Start, 2003, 49.99<, 8Learning XML, 2003, 39.95<<
Load books into the Database
MapIndexed@
SQLInsert@bookstore, "BOOK", 8"ID", "TITLE", "YEAR", "PRICE"<, 2 ~ Join ~ 1D &, booksD;
In[155]:=
Query the Database
SQLSelect@bookstore, "BOOK"D TableForm
In[156]:=
Out[156]//TableForm=
1
2
3
4
Everyday Italian
Harry Potter
XQuery Kick Start
Learning XML
2005
2005
2003
2003
Close the Database Connection
30.
29.99
49.99
39.95
FunctionalProgramming-Egypt-2010.nb
Close the Database Connection
In[157]:=
CloseSQLConnection@bookstoreD
33
34
FunctionalProgramming-Egypt-2010.nb
Example: Geometric Transformation
The RotationTransform Function
Understanding the Function
In[158]:=
RotationTransform@D
Cos@D -Sin@D 0
Cos@D 0 E
0
0
1
Out[158]= TransformationFunctionA Sin@D
In[159]:=
RotationTransform@D 8x, y<
Out[159]= 8x Cos@D - y Sin@D, y Cos@D + x Sin@D<
Creating a Replacement Rule
In[160]:=
RotationTransform@D 8x, y< . 8a_, b_< 8x a, y b<
Out[160]= 8x x Cos@D - y Sin@D, y y Cos@D + x Sin@D<
Testing Our Rule
In[161]:=
Iy == x2 M . 8x x Cos@D - y Sin@D, y y Cos@D + x Sin@D<
2
Out[161]= y Cos@D + x Sin@D Hx Cos@D - y Sin@DL
In[162]:=
Iy Cos@D + x Sin@D Hx Cos@D - y Sin@DL2 M . 90
2
Out[162]= x y
FunctionalProgramming-Egypt-2010.nb
In[163]:=
ContourPlotA9y x2 , x y2 =, 8x, -2 , 2 <, 8y, -2 , 2 <,
Axes True, Frame False, ContourStyle 88Thick, Red<, 8Thick, Blue<<E
Out[163]=
-6
-4
-2
-2
-4
-6
Creating a Simple Rotate Function
In[164]:=
rotate@eq_, _D := Heq . HRotationTransform@D 8x, y< . 8a_, b_< 8x a, y b<LL
In[165]:=
9rotateAy == x2 , 90 E, rotate@y == Sin@xD, 30 D= FullSimplify
1
2
Out[165]= 9x y , x +
3 y 2 SinA
J 3 x - yNE=
2
35
36
FunctionalProgramming-Egypt-2010.nb
The Rotate Function in Action
In[233]:=
ShowA
ContourPlotA
Hrotate@y Sin@xD, 1 DL Evaluate,
8x, -2 , 2 <, 8y, -2 , 2 <,
Frame False,
Exclusions 99rotate@y Sin@xD, 1 D Evaluate, x2 + y2 > 25==,
1
ContourStyle [email protected], HueA
E=
E & Range@0, 360, 10D
E Magnify@, 1D &
Out[233]=
FunctionalProgramming-Egypt-2010.nb
Example: Tree Chains
Graph Algebraic Data Type
Graph Structure and supporting functions
In[167]:=
ClearAll@Graph, graph, Vertex, vertex, Leaf, leaf,
Branch, tail, branch, succ, dft, concatMap, chains, toRules, vrfD;
Vertex = VertexT@d$ : _D;
vertex@d_D := VertexT@dD;
value@VertexD := d$;
Graph = GraphT@rep$ : 88_VertexT, 8_VertexT ...<< ...<D;
graph@rep : 88_VertexT, 8_VertexT ...<< ...<D := GraphT@repD;
graph@rep : 88_VertexT 8_VertexT ...<< ...<D :=
GraphT@H . 88x_ y : 8__<< 8x, y<<L & repD;
rep@GraphD := rep$;
Leaf = LeafT@v$ : VertexD;
leaf@v : VertexD := LeafT@vD;
vertex@LeafD := v$;
Branch = BranchT@v$ : Vertex, tail$ : 8__<D;
branch@v : Vertex, 8<D := leaf@vD;
branch@v : Vertex, l : 8___<D := BranchT@v, lD;
vertex@BranchD := v$;
tail@BranchD := tail$;
succ@g : Graph, v : VertexD := Cases@rep g, 8u : Vertex, adj_< ; u == v adjD Flatten;
dft@g : Graph, v : VertexD := branch@v, dft@g, D & succ@g, vDD;
concatMap@f_, l : 8__<D := Fold@Join, 8<, 8Flatten f < & lD;
chains@g : GraphD := chains@dft@g, Hrep gL@@1DD@@1DDDD;
chains@l : LeafD := 88vertex l<<;
chains@b : BranchD := HconcatMap@8vertex b, < &, chains@DDL & tail b Flatten@, 1D &;
toRules@g : GraphD := H . 88x_, y : 8__<< HHx L & yL<L & rep g Flatten;
toRules@ch : 8_VertexT ...<D := ch . 88x_< 8<, 8x_, y_, xs___< 8Hx yL< ~ Join ~ toRules@8y, xs<D<;
toRules@chs : 88_VertexT ...< ...<D := toRules@D & chs;
vrf = 8ps, v< 8White, EdgeForm@BlackD, Disk@ps, .3D, Black, Text@value v, psD<;
Graph Instance
In[193]:=
Dynamic@gD;
g = graph@8
8vertex@D vertex 8, , <<,
8vertex@D vertex 81 , 2 , 3 <<,
8vertex@D vertex 81 , 2 , 3 <<,
8vertex@D vertex 81 , 2 , 3 <<<D;
37
38
FunctionalProgramming-Egypt-2010.nb
Graph Plot
In[219]:=
LayeredGraphPlot@g toRules, VertexRenderingFunction vrfD Magnify@, 1D & Dynamic
Out[219]=
Chains and Chains Plot
In[196]:=
chains@gD Dynamic
Out[196]= 88VertexT@D, VertexT@D, VertexT@1 D<,
8VertexT@D,
8VertexT@D,
8VertexT@D,
8VertexT@D,
In[220]:=
Out[220]=
VertexT@D,
VertexT@D,
VertexT@D,
VertexT@D,
VertexT@2 D<,
VertexT@1 D<,
VertexT@3 D<,
VertexT@2 D<,
8VertexT@D,
8VertexT@D,
8VertexT@D,
8VertexT@D,
VertexT@D,
VertexT@D,
VertexT@D,
VertexT@D,
VertexT@3 D<,
VertexT@2 D<,
VertexT@1 D<,
VertexT@3 D<<
8GraphPlot@, VertexRenderingFunction
vrfD Magnify@, 1D &< & toRules chains g Partition@, 3D & TableForm Dynamic
FunctionalProgramming-Egypt-2010.nb
Example: Sound
The Sound of Mathematics
In[198]:=
n11 = 811, 2, 7, 9, 11, 2, 7, 5, 11, 2, 7, 4, 2, 2, 2<;
a11 = n11 ;
a12 = + 12 & n11 ;
a13 = a12 ~ Join ~ a11 ;
a14 = a13 ~ Join ~ Reverse@a12 D ~ Join ~ n11 ;
s1 = Sound@SoundNote@, .1, "Flute"D & Ha14 LD;
n21 = 82, 3, 7, 2, 3, 7, 2, 3, 9, 9, 7, 3<;
a21 = n21 ;
a22 = H + 12 & n21 L . 8xs__< 8xs, xs<;
a23 = a22 ~ Join ~ a21 ~ Join ~ Reverse@H + 12 & a21 LD ~ Join ~ Reverse@a21 D;
s2 = Sound@SoundNote@, .1, "Piano"D & Ha23 LD;
EmitSound@8s1 , s2 <D
39