To run this code, first run MW-Time-Init.nb, then run everything in the next section. Then try the examples at the end. See description of options in DirectedNeighborsPicture::usage. This version doesn't yet implement ribbon-edges. Note that the example uses the Hyperbola view, which allows for straight lines between nodes at the same time level, and perhaps looks better for this reason.

DirectedNeighborsPicture code

DirectedNeighborsPicture[g_,init_,opts___?OptionQ]:=Module[{a,b,c,d,already,time,nodecoordinates,wts,maxt,weight,coords,psep,dip,hyperbola,reord,sym,ar,cone,nodesize,arrows,arrowlength,arrowangle,arrowlocation,up},{reord,sym,ar,cone,hyperbola,nodesize,dip,psep,arrows,arrowlength,arrowangle,arrowlocation}={Reordered,Symmetrized,AspectRatio,LightCone,Hyperbola,NodeSize,Dip,ParallelSeparation,Arrows,ArrowLength,ArrowAngle,ArrowLocation}/.{opts}/.Options[DirectedNeighborsPicture];​​​​ (*Thenodesattimetarecomputedandputintime[t].Thesearethenodeswhoseminimalforwarddistance​​ fromtheinitialnode(orinitialnodes)ist.The{space,time}coordinatesofnodeiareputin​​ nodecoordinates[i].IfReordered->True,thenodesatattimet(forfixedt>0)arespatiallyreorderedtotrytoreducehowmanyedges​​ crossoneanother.Togettheorder,weassignweightstoeachoftheedgesattachingnodeitonodesatprevioustimes,addingtheweights,andorderingthenodesinorderofincreasingweights.Theweightforanedgeattachingnodeiattimettonodejattimet-kisequaltothespatialpositionofnodejdividedby(numberofnodesattimet-ktimesk).*)​​ ​​ time[0]=init;​​ already={};​​ maxt=0;​​ weight[{node_,z_,numberofedges_}]:=Function[x,{(numberofedges*x〚1〛)/((Length[time[x〚2〛]]+1)*(maxt-x〚2〛)),numberofedges/(maxt-x〚2〛)}]@nodecoordinates[node];​​ While[time[maxt]≠{},​​ already=Union[already,time[maxt]];​​ MapIndexed[(nodecoordinates[#1]={First[#2],maxt})&,time[maxt]];​​ maxt++;​​ time[maxt]=Complement[Flatten[(First/@Cases[#,_?((#〚2〛>0)&)])&/@(time[maxt-1]/.g)],already];​​ If[reord,wts=((#〚1〛/#〚2〛)&@(Plus@@weight/@Cases[#,_?(MemberQ[already,#〚1〛]&)]))&/@(time[maxt]/.g);​​ time[maxt]=Last/@Sort[Transpose[{wts,time[maxt]}]]]​​ ];​​ ​​ (*Givenapointinthecoordinatesusedabove(e.g.,giventhelocationofnodeiasnodecoordinates[i])theactualgraphicallocationofthepointdependsontheoptionsSymmetrized,LightConeandHyperbola.This​​ routinecomputesthosecoordinates.Eachtimesliceiscenteredat0ifSymmetrized->True,andstartat0andgoestotheleftifnot.ThespacelikeslicesareonhyperbolasifHyperbola->Trueandonhorizontallinesifnot.Timemovesdown.ThisisthepictureifLightCone->True;ifnot,thewholepictureisrotated90degreescounterclockwise.*)​​ ​​ coords[{x_,t_}]:=Module[{xx,tt},​​ xx=If[sym,x-.5*(Length[time[t]]+1),x-1];​​ tt=If[hyperbola,If[t==0,0,Sqrt[t^2+xx^2]],t];​​ If[cone,{xx,-tt},{tt,xx}]];​​ ​​ (*Nowitistimetodrawthenetwork.IfHyperbola->FalsethenthemodeledgebetweennodesonthesametimeslicedipsdownwardbytheparameterDip;otherwiseallmodeledgesarestraightlines(thoughiftherearemultipleedgesbetweenthesametwonodesthentheyvaryfromthemodeledgebyparameterParallelSeparation).Alledgesarequadraticcurves.*)​​ ​​ Flatten[Table[{If[nodesize>0,Graphics[Disk[coords[nodecoordinates[g〚i,1〛]],nodesize],AspectRatio->ar],{}],Table[If[g〚i,1〛<g〚i,2,j,1〛,Table[QuadraticCurve[{a,b}=coords[nodecoordinates[g〚i,1〛]];{c,d}=coords[nodecoordinates[g〚i,2,j,1〛]];{{a,b},{If[cone||hyperbola||(a≠c),0,dip]+(a+c)*.5+psep(k-(g〚i,2,j,3〛+1)/2)(d-b),If[!cone||hyperbola||(b≠d),0,-dip]+(b+d)*.5+psep(k-(g〚i,2,j,3〛+1)/2)(a-c)},{c,d}},arrows,arrowlength,arrowangle,arrowlocation,ar,If[k>g〚i,2,j,2〛,False,True]],{k,g〚i,2,j,3〛}],{}],{j,Length[g〚i,2〛]}]},{i,Length[g]}]]]​​
DirectedNeighborsPicture::usage="DirectedNeighborsPicture[g,init,opts] produces a set of graphic objects which represent the causal network given in g. g is a list of items of the form 0->{{a1,a2,a3},{b1,b2,b3},...} where this means that: there are a2 edges going from node 0 to node a1 and a3-a2 edges going from node a1 to node 0; there are b2 edges going from node 0 to node b1 and b3-b2 edges going from node b1 to node 0; and so on. (This is the form of the output to SMWEvolveListNW.) init is a list containing nodes to put at the top of the network. Options: Reordered->True attempts to order the nodes on each horizontal row to eliminate crossings; Symmetrized->True centers the nodes horizontally; NodeSize is the size of disks drawn at nodes; AspectRatio is the aspect ratio; LightCone->True presents the picture the way I have described it (initial nodes at top, picture is created downwards); if it's false then initial nodes are at left and picture grows to the right; ParallelSeparation is the amount that parallel edges are separated; Dip is the amount that edges between nodes at the same time slice dip downward (if not in Hyperbola mode); Hyperbola->True puts nodes at the same time slice on hyperbolas; Arrows->True gives arrows on the edges; ArrowLength specifies the length of the line segments making up the arrows; ArrowAngle specifies the angle those segments make with the edge; ArrowLocation is a number between 0 and 1 which specifies where the arrow is on the edge (default is .6).";
DirectedNeighborsPictureR[args___]:=DirectedNeighborsPicture[args,Reordered->True]
Options[DirectedNeighborsPicture]={Reordered->False,Symmetrized->True,ParallelSeparation->.1,Dip->.35,Hyperbola->False,NodeSize->0,AspectRatio->Automatic,LightCone->True,Arrows->False,ArrowLength->.1,ArrowAngle->Pi/6,ArrowLocation->.6};
QuadraticCurve[{{a_,b_},{c_,d_},{e_,f_}},arrows_,arrowlength_,arrowangle_,arrowlocation_,ar_,up_]:=Module[{coefs,fx,fy,tangentvector,len,loc},​​ coefs={2#〚3〛-4#〚2〛+2#〚1〛,-#〚3〛+4#〚2〛-3#〚1〛,#〚1〛}&/@{{a,c,e},{b,d,f}};​​ {fx,fy}=Function[t,{t^2,t,1}.#]&/@coefs;​​ loc=If[up,arrowlocation,1-arrowlocation];​​ tangentvector=(2loc#〚1〛+#〚2〛)&/@coefs;​​ len=arrowlengthSqrt[tangentvector.tangentvector];​​ tangentvector=-len(tangentvector);​​ {ParametricPlot[{fx[t],fy[t]},{t,0,1},DisplayFunction->Identity,AspectRatio->ar,PlotRange->All,Axes->False],If[arrows,Graphics[Line[{{fx[loc],fy[loc]},{fx[loc]+{Cos[#],-Sin[#]}.tangentvector,fy[loc]+{Sin[#],Cos[#]}.tangentvector}}]&/@If[up,{arrowangle,-arrowangle},{Pi+arrowangle,Pi-arrowangle}],PlotRange->All,AspectRatio->ar],{}]}]
QuadraticCurve::usage="QuadraticCurve[{{a,b},{c,d},{e,f}},arrows,arrowlength,arrowangle,arrowlocation,ar,up] creates a list of graphics objects for the quadratic curve beginning at {a,b}, passing through {c,d} and ending at {e,f}. If arrow is true, it then draws an arrow pointing towards {e,f} if up is true and towards {a,b} if up is false. The arrow is controlled by the following parameters: arrowlength is the length of the two line segments that make up the arrow (currently this is a coordinate length, not an absolute length); arrowangle is the angle these lines make with the tangent to the curve; arrowlocation is the value of the parameter t where the arrow is to be drawn (t=0 at {a,b}, .5 at {c,d} and 1 at {e,f}). Also, ar is the aspect ratio.";
TransformNW[s_]:=Module[{g,nodes,connectnodes},​​ g=(First/@#)&/@s;​​ nodes=Union[Flatten[g]];​​ connectnodes=(Union[g〚#〚1〛,3-#〚2〛〛&/@Position[g,#]])&/@nodes;​​ MapThread[Function[{x,y},x->({#,Count[g,{x,#}],Count[g,{x,#}|{#,x}]}&)/@y],{nodes,connectnodes}]]
TransformNW::usage="TransformNW[s] deals with directed networks with parallel edges. It takes input from SMWEvolveListNW0 and produces a list of items of the form 0->{{a1,a2,a3},{b1,b2,b3},...} where this means that: there are a2 edges going from node 0 to node a1 and a3-a2 edges going from node a1 to node 0; there are b2 edges going from node 0 to node b1 and b3-b2 edges going from node b1 to node 0; and so on.";

Examples

TransformNW[SMWEvolveListNW0[SMWEvolveListX[{"ABA""BAAB","BBBB""AA"},"ABAAB",50]]];
Show[DirectedNeighborsPictureR[SMWEvolveListNW[{"ABA""BAAB","BBBB""AA"},"ABAAB",25],{0},NodeSize->.065,Hyperbola->True,Arrows->True],DisplayFunction->$DisplayFunction];