I have a package developed in earlier versions of Mathematica. In it, I use the notation x_ <-> y_ for undirected edges.

When I use this package in 11.2, Mathematica does not match <-> to an undirected edge.

For example, if I define

edge2Distance[x_ <-> y_] := geoDistance[x, y]

in the package, it does not match a call like:

edge2Distance /@ EdgeList[g]

I could rewrite the entire package, but it would be bug-prone and the readability of something like this would not be great.

edge2Distance[UndirectedEdge[x_, y_]] := geoDistance[x, y]

Any ideas what could be done?

  • $\begingroup$ Worth to mention that the reason is probably a TwoWayRule. $\endgroup$ – Kuba Oct 26 '17 at 10:03
  • $\begingroup$ Yep, that's probably an arguable choice: EdgeList@Graph[{TwoWayRule[a, b]}] --> {a \[UndirectedEdge] b} $\endgroup$ – Kuba Oct 26 '17 at 10:14

As Kuba notes, this is a recent breaking change; 11.2 now interprets a <-> b as TwoWayRule[a, b] instead of UndirectedEdge[a, b].

You might want to define a new EdgeList[] function that will convert UndirectedEdge[] into TwoWayRule[]:

myEdgeList[g_Graph] := TwoWayRule @@@ EdgeList[g]

and then use $VersionNumber to help your code choose which version to use.

As Stephen Wolfram says in the 11.2 release blog post:

Another language enhancement added in 11.2—though it's really more of a seed for the future—is TwoWayRule, input as <->. Ever since Version 1.0 we've had Rule (->), and over the years we've found Rule increasingly useful as an inert structure that can symbolically represent diverse kinds of transformations and connections. Rule is fundamentally one-way: "left-hand side goes to right-hand side". But one also sometimes needs a two-way version—and that's what TwoWayRule provides.

Right now TwoWayRule can be used, for example, to enter undirected edges in a graph, or pairs of levels to exchange in Transpose. But in the future, it'll be used more and more widely.

(This got too long for a comment.)

  • 1
    $\begingroup$ Thanks, now I understand why this happens. As a workaround I will probably make a global replace of <-> to ~UndirectedEdge~ $\endgroup$ – MCed Oct 26 '17 at 12:41

Here's a possible workaround, if it is not already the case, add Kernel/init.m to your package.

  |  ...
  |- MyPackage.m
  |- Kernel
      |  ...
      |- init.m

While normally init.m contains:

<< MyPackage`MyPackage`

you will change it:

Block[{TwoWayRule = UndirectedEdge},
    << MyPackage`MyPackage`

And this should fix it. init.m is the first thing that loads if it exists in the package.

It is limited to things that evalaute during package loading, such as lhs of set delayed here.

It will work until TwoWayRule is Locked but it probably won't be so don't worry and now it only is Protected.

Here is a quick check of this method:

Block[{TwoWayRule = UndirectedEdge},


enter image description here


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.