29
$\begingroup$

Lately I've been doing algebra and I have found myself drawing a bunch of diagrams when I attempt to solve a problem. Most of the diagrams are very simple so I thought, I bet I can do this in Mathematica and include these pictures in a nice document. What I would like to do is create diagrams like the ones found in category theory:

img1

img2

Here is an attempt based on a solution provided by Mr.Wizard

vertex = {
    {White, Disk[#2, 0.04]},
    Text[#, #2]
    } &;
GraphPlot[{
   {"A" -> "B", "f"},
   {"A" -> "C", "h"},
   {"B" -> "C", "g"}
   },
  DirectedEdges -> True,
  VertexLabeling -> True
  ] /. {Text -> vertex, Framed -> (# &)}

img3

I like the idea of how in GraphPlot you can define the vertices and the labels. Unfortunately I'm still not very savvy on controlling many aspects of the Graphics. Does anyone know how to create diagrams like the ones I'm attempting to draw? It would be awesome if the font size could be specified.

Edit:

As belisarius pointed out:

Text length and font size should be considered with care

As requested by Mr.Wizard, here is are some interesting diagrams:

https://scientopia.org/blogs/goodmath/category/good-math/category-theory/

imglink1 imglink2
(source: pdp7.org)

The second picture can be found here

A quick search on google images for "category theory diagrams" will give you some other diagrams including the ones I have put in here. It seems based on the figures that most of them involve simple rectangles with diagonal lines. In some cases some lines might be curved but this can all be done with straight lines.

Since the arrangement of the lines is up to personal choice it would be good to have a solution in which we can move the vertices locations, a similar functionality should be done with the edge labels. I picture an edge label as an image that can rotate around a point in a line. That way we can select a position in the line and the position angle. In most cases this angle is multiples of 45 degrees.

$\endgroup$
11
  • 3
    $\begingroup$ Text length and font size should be considered with care en.wikipedia.org/wiki/Monad_(category_theory)#Formal_definition $\endgroup$ Jul 24, 2012 at 5:08
  • $\begingroup$ Can you provide a reference to a range of these diagrams? For example I am wondering of they are always a rectangle or a diagonal across a rectangle as shown? That would be pretty easy to write a specific function for. $\endgroup$
    – Mr.Wizard
    Jul 24, 2012 at 6:20
  • $\begingroup$ Use VertexCoordinates or GraphLayout to "move the vertices locations". Use Placed, Rotate and even `EdgeShapeFunction' to play with edge labels placement. $\endgroup$ Jul 24, 2012 at 7:06
  • $\begingroup$ Take a look at this package. I haven't used it, but I have it installed, and it seems it can create diagrams. $\endgroup$
    – Szabolcs
    Jul 24, 2012 at 7:20
  • 4
    $\begingroup$ Indeed , as @Szabolcs mentioned, WildCats is a category theory package for Mathematica. I am the developer. WildCats can plot commutative (and non-commutative) categorical diagrams. But it can do much more. It can do (some) calculations in category theory, both symbolically and -when appropriate- visually using diagrams. I am preparing a more complete answer with examples, shortly $\endgroup$
    – magma
    Jul 24, 2012 at 8:25

3 Answers 3

31
$\begingroup$

WildCats is a category theory package for Mathematica. It is still under development. Current version is 0.51.0

I am the developer.

WildCats can plot commutative (and non-commutative) categorical diagrams.

But it can do much more. It can do (some) calculations in category theory, both symbolically and - when appropriate - visually, using diagrams. This is because, in WildCats, diagrams are not just pretty pictures, but retain most of their mathematical semantic. So it is possible to input a diagram to a functor (which is an operator between categories) and obtain a new diagram. Functors are operators which preserve the topology of diagrams (that means: it transforms vertices and arrows and an arrow between 2 vertices is transformed into an arrow between the transformed 2 vertices).

Let me show some of the current diagram-drawing capabilities in WildCats and give some flavour of category theory along the way.

The following example is taken from the "Displaying diagrams" tutorial.

We are in the category (cat in some popular textbook) Grp, containing groups and their group-homomorphisms. Wildcats knows something about 27 well-known cats, but you can build your own cats too and derive new cats from old cats...that's why they can get wild pretty soon :-).

Grp is the category of groups.

We define 4 groups (g1...g4) and 3 group-homomorphisms (f1...f3) between them. They are the objects and morphisms in Grp. The following code defines the groups and morphisms.

Mathematica graphics

When we define a morphism (an arrow) in Category theory, we must always specify where it starts and where it ends. So here f1 goes from groups g1 to g2.

WildCats at this point knows that we can compose the various morphisms and where the composite morphisms should start and end. Composite morphisms are represented as

Op[f2,f1,Grp]

or, even better, as

Mathematica graphics

since WildCats uses custom notation for almost everything.

We can visualize all this with a CategoryPlot

Mathematica graphics

Mathematica graphics

The DC functions find the Domain and Codomain of an arrow (its starting and ending vertex)

As you see I just tell CategoryPlot which arrows I want to draw and it does the rest by itself (with just some help for the coordinates of the vertices).

The above diagram visually says that the composition in Grp is associative, that is

Mathematica graphics

something that WildCats knows well.

Another example might be

Mathematica graphics

It visually represents the relations

Mathematica graphics

describing the fact that Id (identity morphisms) are bilateral identities in the morphism-composition. Notice that the same vertex (eg. g1) appears to be displayed in 2 different locations. This is not easily possible in standard Mathematica.

This is a visual depiction of the structure of (some of) the mathematical knowledge of WildCats (some standard categories and their relations).

Mathematica graphics

The tantalizing thing in WildCats is that you can take a diagram, give it to a functor and get another diagram!

This is an example taken from the Tutorial "Functors". I won't go into the mathematical details too deeply.

Suppose you have some groups and homomorphims in a diagram cp

Mathematica graphics

Now we tell WildCats that g4 is the Quaternions group (a group with 8 elements)

Mathematica graphics

and apply to the above diagram the forgetful functor U[Grp , Set] which forgets the group structure and gives the underlying set of a group

Mathematica graphics

As you see the groups IntegersPlus and RealsPlus (groups of numbers with the Plus operation) have become the simple sets Z and R of integers and reals (without any specific operation),Ab0, the trivial group, has become the Singleton set, while the g4 (the quaternions group) has become a simple set with 8 elements. Also notice that the composition in Grp is now a composition in Set the category of sets and functions.

In the future releases of WildCats, I would like to use some Dynamic features to bring life (and even more intuition) to all these diagram drawing.

Anyone interested in testing/using WildCats, can contact me at maderri2 at gmail dot com

$\endgroup$
10
  • $\begingroup$ Hey magma, this is pretty interesting. But I cannot follow it. How do you get the $\mathbb{Grp}$? Could you perhaps include a screenshot of the things that you click on the palette? $\endgroup$
    – jmlopez
    Jul 24, 2012 at 14:29
  • $\begingroup$ there is no palette at the moment. Will be made soon. For now, just write it with doublescripted characters or copy/paste it from one of the tutorials. Watching a webseminar from WRI now, I will be back in 2 hours. Where is the popcorn ? :-) $\endgroup$
    – magma
    Jul 24, 2012 at 15:02
  • $\begingroup$ @jmlopez Here's a palette button: PasteButton[\[DoubleStruckCapitalG]\[DoubleStruckR]\[DoubleStruckP]] $\endgroup$
    – Szabolcs
    Jul 24, 2012 at 18:01
  • $\begingroup$ I meant: doublestruck characters. You can find them in the Special characters palette. But the fastest way is probably to evaluate StandardCategories and then copy/paste from its output. $\endgroup$
    – magma
    Jul 24, 2012 at 18:01
  • $\begingroup$ Or type ESC dsG ESC. $\endgroup$
    – Szabolcs
    Jul 25, 2012 at 6:45
12
$\begingroup$

After exploring phantomas1234 answer and the useful comments from Vitaliy Kaurov I have made a simple module which does what I want.

(* See bug fix bug below. *)
PlotDiagram[vertex_List, edge_List, args___] := Module[
  {
   v, vl, vp,
   e, el, es
   },
  v = Range[Length@vertex];
  vl = Table[vertex[[i, 1]], {i, 1, Length@vertex}];
  vp = Table[vertex[[i, 2]], {i, 1, Length@vertex}];
  e = Table[edge[[i, 1]], {i, 1, Length@edge}];
  el = Table[edge[[i, 2]], {i, 1, Length@edge}];
  es = Table[edge[[i, 3]], {i, 1, Length@edge}];
  Graph[e,
   VertexCoordinates -> vp,
   VertexLabels -> 
    Table[v[[i]] -> Placed[vl[[i]], {0.5, 0.5}], {i, 1, Length[v]}],
   EdgeLabels -> Table[e[[i]] -> el[[i]], {i, 1, Length[e]}],
   EdgeShapeFunction -> Table[e[[i]] -> es[[i]], {i, 1, Length[e]}],
   args,
   VertexLabelStyle -> Directive[Italic, 18],
   EdgeLabelStyle -> Directive[Italic, 15],
   VertexSize -> 0,
   VertexStyle -> Directive[EdgeForm[], White]
   ]
  ]

The default behavior is to make the diagram with vertex labels of font size 18 and the edge labels of font size 15. The first argument of the function has be a list containing the vertex labels and the positions of the vertices. The second argument is a list containing the edges. Each entry in edges is a list of 3 elements. The first one specifies the edge, the second specifies the label and the third specifies the arrow to be used. After that you may use any option you want for Graph. For a simple example I will make the figure that I showed in the post.

arrowShape =  ({Black, Arrowheads[0.1], Arrow[#, {2, 2}]} &);
vertex = {
   {"X", {0, 10}},
   {"Y", {10, 10}},
   {"Z", {10, 0}}
  };
edge = {
   {1 \[DirectedEdge] 2, Placed["f", {.5, {.5, -0.2}}], arrowShape},
   {2 \[DirectedEdge] 3, Placed[ "g", {.5, {-1.2, .5}}], arrowShape},
   {1 \[DirectedEdge] 3, Placed[ "g\[SmallCircle]f", {.5, {1.2, 1.2}}], arrowShape}
  };
graph = PlotDiagram[
  vertex, edge, 
  AspectRatio -> 1,
  ImageSize -> 2*72,
  ImagePadding -> {{15, 15}, {5, 20}}
 ]
Export["graph1.png", graph]

graph1

vertex = {
   {"T", {0, 10}},
   {Superscript["T", 2], {10, 10}},
   {"T", {20, 10}},
   {"T", {10, 0}}
  };
edge = {
   {1 \[DirectedEdge] 2, Placed["Tη", {.5, {.5, -.2}}], ({Black, Arrowheads[0.05], Arrow[#, {2, 2}]} &)},
   {3 \[DirectedEdge] 2, Placed[ "ηT", {.5, {.5, -.2}}], ({Black, Arrowheads[0.05], Arrow[#, {2, 2}]} &)},
   {2 \[DirectedEdge] 4, Placed[ "μ", {.5, {-1.2, -.5}}], ({Black, Dashed, Arrowheads[0.05], Arrow[#, {1, 1}]} &)},
   {1 \[DirectedEdge] 4, Placed[ "id", {.5, {2, 1.2}}], ({Black, Arrowheads[0.05], Arrow[#, {2, 2}]} &)},
   {3 \[DirectedEdge] 4, Placed[ "id", {.5, {-1.2, 1.2}}], ({Black, Arrowheads[0.05], Arrow[#, {2, 2}]} &)}
  };
graph = PlotDiagram[
  vertex, edge, 
  AspectRatio -> 1/GoldenRatio,
  ImageSize -> 4*72,
  ImagePadding -> {{15, 15}, {5, 20}}
 ]
Export["graph2.png", graph]

graph2

Notice how I was able to change the style of one of the edges. We can even change the tip of the arrow by using something similar as in one of the examples at Wolfram website.

Bug Fix

Special thanks to Frederick Fritz Fisher for pointing out the bug. The PlotDiagram module has a very simple problem. I neglected to use the vertices when using Graph. The correct form should be this:

PlotDiagram[vertex_List, edge_List, args___] := Module[
  {
   v, vl, vp,
   e, el, es
   },
  v = Range[Length@vertex];
  vl = Table[vertex[[i, 1]], {i, 1, Length@vertex}];
  vp = Table[vertex[[i, 2]], {i, 1, Length@vertex}];
  e = Table[edge[[i, 1]], {i, 1, Length@edge}];
  el = Table[edge[[i, 2]], {i, 1, Length@edge}];
  es = Table[edge[[i, 3]], {i, 1, Length@edge}];
  Graph[v, e,
   VertexCoordinates -> vp,
   VertexLabels -> 
    Table[v[[i]] -> Placed[vl[[i]], {0.5, 0.5}], {i, 1, Length[v]}],
   EdgeLabels -> Table[e[[i]] -> el[[i]], {i, 1, Length[e]}],
   EdgeShapeFunction -> Table[e[[i]] -> es[[i]], {i, 1, Length[e]}],
   args,
   VertexLabelStyle -> Directive[Italic, 18],
   EdgeLabelStyle -> Directive[Italic, 15],
   VertexSize -> 0,
   VertexStyle -> Directive[EdgeForm[], White]
   ]
  ]

If you use the old version, you will not obtained the expected results here:

arrow[dash_: {}, start_: 2, stop_: 2] := ({
    Black,
    Dashing[dash],
    Arrowheads[0.05],
    Arrow[#, {start, stop}]
    } &)
vertex = {
    {Subscript["A", 1], {0, 10}},
    {"A", {10, 10}},
    {Subscript["A", 2], {20, 10}},
    {"C", {10, 0}}
};
edge = {
    {2 \[DirectedEdge] 1, Placed[Subscript["\[Pi]", 1], {.5, {.5, -.2}}], arrow[]},
    {2 \[DirectedEdge] 3, Placed[Subscript["\[Pi]", 2], {.5, {.5, -.2}}], arrow[]},
    {4 \[DirectedEdge] 2, Placed["p", {.5, {-1.2, -.5}}], arrow[{0.02}, 1, 1]}, 
    {4 \[DirectedEdge] 1, Placed[Subscript["p", 1], {.5, {2, 1.2}}], arrow[]},
    {4 \[DirectedEdge] 3, Placed[Subscript["p", 2], {.5, {-1.2, 1.2}}], arrow[]}
};
graph = PlotDiagram[
    vertex,
    edge,
    AspectRatio -> 1/GoldenRatio,
    ImageSize -> 4*72,
    ImagePadding -> {{15, 15}, {5, 20}}
]

If you see this abomination then you are still using my first shameful function.

wrong-display

Instead by using the fixed version you can obtain the desired figure:

correct-display

Notice the inclusion of the arrow function so that we can specify a level of dash, and then values to specify where the arrow starts and stops. This is seen in the specification for the edge from 4 to 2.

$\endgroup$
2
  • 1
    $\begingroup$ Since you're using graph objects, there are some predefined arrow heads available. See this answer for an idea $\endgroup$
    – rm -rf
    Jul 24, 2012 at 18:16
  • $\begingroup$ Those diagrams look really good. $\endgroup$
    – murray
    Jul 26, 2012 at 19:36
11
$\begingroup$

I don't like the new Graph functionality, but in your case it might be easier to use for label styling etc.

ef1[el_, ___] := Arrow[el, 0.1]
vertexLabels = 
MapIndexed[#2[[1]] -> 
 Placed[Style[#, Opacity[1], Background -> White], {1/2, 
   1/2}] &, {F[X], F[Y], G[Y], G[X]}];
Graph[{Property[1 \[DirectedEdge] 2, EdgeLabels -> F[f]], 
       Property[2 \[DirectedEdge] 3, EdgeLabels -> ηγ], 
       Property[1 \[DirectedEdge] 4, EdgeLabels -> ηx], 
       Property[4 \[DirectedEdge] 3, EdgeLabels -> G[f]]}, 
    VertexLabels -> vertexLabels,
    ImagePadding -> Scaled[.1], 
    VertexSize -> 0,
    VertexLabelStyle -> Directive[Italic, 20], 
    EdgeLabelStyle -> Directive[Italic, 20],
    EdgeStyle -> Black, 
    EdgeShapeFunction -> ef1,
    VertexStyle -> None, GraphLayout -> "SpringEmbedding" (*Thanx Vitaliy*)]

enter image description here

$\endgroup$
3
  • $\begingroup$ Option GraphLayout -> "SpringEmbedding" will make it "more square" ;-) $\endgroup$ Jul 24, 2012 at 5:38
  • $\begingroup$ I tried a few of the layout alogorithms using the context menu (right mouse click) but for some reason I forgot SpringEmbedding, thank you @VitaliyKaurov $\endgroup$ Jul 24, 2012 at 5:52
  • 2
    $\begingroup$ +1 I am glad you used Graph and not GraphPlot. BTW I do not think it is necessary, but if OP doesn't like edge crossing over label Placed is the way to deal with this: reference.wolfram.com/mathematica/ref/EdgeLabels.html#72169267 $\endgroup$ Jul 24, 2012 at 6:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.