Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edge list #67

Merged
merged 3 commits into from
Mar 20, 2019
Merged

Edge list #67

merged 3 commits into from
Mar 20, 2019

Conversation

ferranpujolcamins
Copy link
Collaborator

In this PR I added a directedproperty to edges. I also added a new edgeList() method to Graph that returns a list of edges, but does not return the undirected edges twice (as opposed to edges.joined()).

With this changes we will be able to export graphs to DOT format for Graphviz.

I also changed the way undirected loops (edges starting and ending at the same vertex) are represented. Before, they were represented with two edges, like all other undirected edges. Now they are represented with a single edge, like we already were doing in UniqueElementsGraph.
This change was necessary to implement edgeList() efficiently, but also makes all the types of graph consistent in the way they represent undirected loops.

@davecom
Copy link
Owner

davecom commented Mar 16, 2019

This might frustrate you to know, but the original version of SwiftGraph, way back in 2014, actually had a directed property on all Edges. This was later taken out as a simplification. If you think about it (and I'm sure you have), an undirected graph is actually just a directed graph with every edge being bidirectional. You don't really save much with the property. You add an additional property (more complexity) and then you still have to add the edge to both sides of the adjacency list (both u and v need to have it added to their adjacency lists for fast lookup).

My alternative suggestion would be to code a specialized function that checks if an edge exists in both directions and use that before exporting to DOT. If this is just for DOT, then I'm not sure I want to change the whole project for it when we could do it with a "middleware" function.

I assume for DOT you cannot have mixed graphs with both undirected and directed edges in them? Either way, would you mind I coded up an example of a function that would return the undirected edges? If so, would you just need a list of the vertices on each edge and the edge that connected them? I could deliver this as an array of tuples maybe? Once we are exporting, I guess we don't need the richness of the original data structure but just an intermediary format? That's my key question for you.

@ferranpujolcamins
Copy link
Collaborator Author

ferranpujolcamins commented Mar 16, 2019

Hi Dave, thanks for your comment. I still think this is a good addition. Here's why:

and then you still have to add the edge to both sides of the adjacency list

Yes, I tried to store the edges only one in an array, and then store only the indices to that array on the incidence matrix, but this destroyed performance :(

My alternative suggestion would be to code a specialized function that checks if an edge exists in both directions and use that before exporting to DOT.

This solution would be ok for me. But I'm afraid it doesn't work for all graphs. What should DotSwift print for the graphs below?:

let g1 = UnweightedGraph(vertices: ["A", "B"])
g1.addEdge(from: "A", to: "B", directed: false)

let g2 = UnweightedGraph(vertices: ["A", "B"])
g2.addEdge(from: "A", to: "B", directed: true)
g2.addEdge(from: "A", to: "B", directed: true)

For g1 I would expect this:
graph

For g2 I would expect this:
digraph

But currently g1 and g2 are the same graph in SwiftGraph! How can we generate two different dot files?

If this is just for DOT, then I'm not sure I want to change the whole project for it when we could do it with a "middleware" function.

IMO, this is not only for DOT, since the directedness of an edge is meaningful in some domains. For example, consider a graph that maps an underground gallery of tunnels. Some tunnels are one-direction only (maybe they are too steep to climb back?). You need to go from A to B to perform some mining job. You need to roll a power cable along the path so you can use your tools. You will need to come back to A through the same path, otherwise you won't be able to take the cable.

Or maybe our graph represent states of a system and edges are state transitions. We have state transitions that are reversible and state transitions that are not. We might want to find a series of reversible state transitions from state A to state B (I'm thinking maybe something related to thermodynamics)

As you see, in some domains, it's not the same to have a path from A to B and a path from B to A, than a single path p that you can walk in both directions. Currently SwiftGraph can't handle this distinction.

I assume for DOT you cannot have mixed graphs with both undirected and directed edges in them?

Yes it does! And I got it already working with SwiftGraph (using this branch). You can see it here. This is the generated drawing.

@davecom davecom merged commit dfa7ada into davecom:release2.1/swift5 Mar 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants