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]

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]

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.

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

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.
VertexCoordinates
orGraphLayout
to "move the vertices locations". UsePlaced
,Rotate
and even `EdgeShapeFunction' to play with edge labels placement. $\endgroup$