Erdos
Erdos copied to clipboard
Adding multiple vertices with the same data
Hello,
Let's say I have a Vertex of the following form:
Vertex<MyClass> myVertex = new Vertex<>(myObject.getMessage());
In my program, it is possible for a Vertex with the same data to get graph.addVertex()
'd. I want to be able to stop the graph from adding a Vertex if another one with the same data
exists. I saw that the Vertex.hashCode
is a function of some auto generated ID. If my data source is guaranteed to be unique elements, is it possible to make the hash a function of the data instead of a random ID ?
Thanks for any advice.
hi @Carpetfizz
I may have a solution for you, but first read why we made the Vertex
class instances unique.
the hash is not exactly random id. It is an auto incremented integer.
building in the hashcode
of a message is dangerous. It has been thought of back
then when the library was designed, basically:
- even if the vertex's
hashcode
depends on the message, you will still need to overrideequals()
so that the graph will understand it already has that vertex. - when the lib was first designed, on of it's intents was to easily move vertices from one graph to another and even to duplicate graphs(we didn't do it), therefore we wanted every vertex to be unique, so we don't get collisions and we also didn't override the equals() method.
- we even made
hashcode
final for that purpose inVertex
but you still can do it, my suggestion is very simple:
- graphs receive
IVertex
ingraph.addVertex(..)
- implement a new
IVertex
, that uses most of theVertex
implementation, and write your ownhashcode
and overrideequals(..)
- you are welcome to contribute this new vertex afterwards
hope that helps
Thank you so much! I just copied and pasted the Vertex
code and overrode the following functions:
@Override
public final int hashCode() {
return "unique_vertex".hashCode() + getData().hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
UniqueVertex otherUniqueVertex = (UniqueVertex) obj;
return this.getData().equals(otherUniqueVertex.getData());
}
Now, I'm trying to do the same for DirectedEdge
but but the Edge
class has the following comment in the header:
directed edges with similar vertices and direction are equal (Java equality).
But I'm not finding this to be the case. The edges in the graph keep increasing as I add more of the same edge. Consider the following toString
representation of my graph:
id=null, tag=null::V = {4, 2, 1, 3, } E = {4->2, 2->4, 4->1, 2->1, 4->2, 1->2, 4->3, 2->3, 1->3, }
The Vertex
fix has worked thanks to your help, but the DirectedEdge
4->2 appears twice.
My requirement is that the edge should be the same but the edge's data can be different. I'm using the graph to map geometric relationships between vertices, which can change. So, the edge (1, 2, data=x) and (1,2, data=y) should count as the same edge between (1, 2) but the data should get updated.
Any advice on this would be appreciated.
@Carpetfizz yeah I see. because we wanted to support multi-edges, i.e - multiple edges on the same two vertices, no two edges can be the same, even if they may be isomorphic, so you can
have two edges that may seem the same like 4->2
. but, it should only appear in graphs that support multi edges. In your case it is a bug, that can be fixed as follows:
override the Vertex.getId()
method so it will return the same id for two similar vertices, i.e vertices that have the same data. stringify the hashcode for example.
it should work, since, the graph engine adds and detects edges presence by the id of their vertices.
under the hood, it serializes like this:
public static String getEdgeDesc(IVertex v1, IVertex v2, EDGE_DIRECTION edgeType) {
String res = null;
if(edgeType==EDGE_DIRECTION.DIRECTED) {
res = (v1.getId() + "->" + v2.getId());
}
else if(edgeType==EDGE_DIRECTION.UNDIRECTED) {
int compare = v1.getId().compareTo(v2.getId());
if(compare < 0)
res = v1.getId() + "<->" + v2.getId();
else
res = v2.getId() + "<->" + v1.getId();
}
return res;
}
Thanks again for the response, I think I left out another requirement by accident. I do indeed want a directed multigraph, but multiple edges connecting the same two vertices will definitely contain different data. Will your above solution still work in this scenario?