From igraph.es (edge sequence) to nodes in R - r

I want to set the edge attributes of a certain range of edges in a graph based on the values of the nodes they connect (in R igraph of course).
When I retrieve a certain edge in my graph object, I am served with an edge sequence object:
E(g)[1]
# + 1/2080 edge (vertex names):
# [1] 35->1
class(E(g)[1])
# [1] "igraph.es"
How can I get to the actual edges from that edge sequence? The only relevant function I have found is as_ids:
as_ids(E(g)[1])
# [1] "35|1"
Then I have to split the string to get to the node ids, convert the ids to integers, fetch the nodes using the V(g)[x] notation, check the attributes I am interested in and finally set the edge attribute.
This is an impractical and wasteful process. Is there any more straightforward way to do the same?
I know the %--% notation and in certain cases it solves my issue by allowing me to filter the edges based on node attributes in advance. But in many other cases that notation doesn't help (when edge attribute values have a more complex relationship with node attributes), and I wonder if there is a more general way to get from one edge sequence to the corresponding pair of nodes.

You can use the ends function to get to the vertices:
ends(g, E(g)[1])

Related

Creating a network graph with set node positions and concentrated edges with both circleheads and arrowheads in R

I've been trying to find a way to replicate the following network graph format in R using DiagrammeR/GraphViz, but without success (ignore the thick black arrow on N1): https://i.stack.imgur.com/oHpQz.png
The graph is a directed graph and each edge in a certain direction either ends with an arrowhead (-->) if the edge value is positive, or a circle/odot (--o) if the edge value is negative. Between a pair of nodes (ex. N1 -- A1), there can be an edge N1 --> A1 and an edge A1 --o N1, and these need to be concentrated so that the two edges look like one line with an arrowhead on one end and a circlehead on the opposite end (like this: o--->). These cannot be parallel or look like two edges ideally.
Another requirement is that the nodes have to be in very specific positions and remain there throughout model simulations where edges might change. From what I have tried and the documentation I have read, this is not possible to do in DOT format, but is possible in neato format.
This is where I get a problem. In neato, I can align the nodes exactly where I want them by defining their x,y positions. However, when I use concentrate = true to create the o---> edge from two otherwise parallel edges, only one type of arrowhead remains. So an edge that's supposed to look like o---> ends up looking like ---> or o---.
This is not a problem in DOT format as concentrate = true does what I want it to do, but in DOT I cannot assign exact node positions. I have tried getting around this using node ranks but without much luck. It seems to stack nodes I want in different ranks within the same rank. As well, concentrate = true doesn't seem to work for edges between nodes within the same rank, as it leaves them as two separate curved edges ---> and o--- without concentrating them.
The reason why I need this to work is because I'm running model simulations where the edges change, and I need to generate hundreds of such graphs. For easy comparison, the nodes need to stay in the same place for consistency.
This is the closest I could come up with using neato format (nodes are positioned the way I want but it's not showing the proper o---> for all the black edges minus self-edges; red edges are true one-way links): https://i.stack.imgur.com/YJBY7.jpg
If only the edges showed up as the proper o---> format, this would be perfect for my needs. If you know of any way to fix this issue using DiagrammeR/GraphViz, or even another program, I would be so grateful. Thanks!
You probably don't need concentrate. Look at arrowtail and dir (https://www.graphviz.org/doc/info/attrs.html#d:arrowtail and https://www.graphviz.org/doc/info/attrs.html#d:dir) and neato -n
digraph c {
graph[label="can neato do the work?"]
node[shape=circle]
a [pos="100,100"]
b [pos="200,100"]
c [pos="300,100"]
a->b [dir=both arrowtail=odot]
c->c [dir=both arrowtail=odot arrowhead=none]
}
Giving:

Gremlin: How to obtain outgoing edges and their target vertices in a single query

Given a set of vertices (say, for simplicity, that I start with one: G.V().hasId("something")), I want to obtain all outgoing edges and their target vertices. I know that .out() will give me all target vertices, but without the information about the edges (which have properties on them, too). On the other hand, .outE() will give me the edges but not the target vertices. Can I obtain both in a single Gremlin query?
Gremlin is as much about transforming graph data as it is navigating graph data. Typically folks seem to understand the navigation first which got you to:
g.V().hasId("something").outE()
You then need to transform those edges into the result you want - one that includes the edge data and it's adjacent vertex. One way to do that is with project():
g.V().hasId("something").outE()
project('e','v').
by().
by(inV())
Each by()-modulator supplied to project() aligns to the keys supplied as arguments. The first applies to "e" and the second to "v". The first by() is empty and is effectively by(identity()) which returns the same argument given to it (i.e. the current edge in the stream).
Never mind. Figured this out.
G.V().hasId("something").outE().as("E").otherV().as("V").select("E", "V")

Finding all possible directed graphs given a number of vertices

Is it possible to find all possible directed graphs given a pair of vertices and the information that an edge exists between them? For example if we know the vertices with edge pairs like
1 2
2 3
1 3
The possible directed graphs will be:
1→2, 2→3, 1→3
1→2, 2→3, 3→1
1→2, 3→2, 1→3
1→2, 3→2, 3→1
2→1, 2→3, 1→3
2→1, 2→3, 3→1
2→1, 3→2, 1→3
2→1, 3→2, 3→1
What data-structure to be used here to work with? What can be the working logic?
I was thinking of using adjacency matrix data structure and compute all possible adjacency matrix. Each adjacency matrix will represent a graph. We can use the graph as and when needed for tasks like checking whether cycle is present or not etc.
Apologies that this is more of a discussion than a programming question, but any help will be appreciated
You could maintain one undirected graph data structure G and work with the knowledge that the existence of an edge (u,v) means that there is only one directed edge in a particular instance of digraph possibility D.
If you want to maintain all possible digraphs separately, you would need 2^m many of them, where m is the number of edges. If the vertices and edges are always the same and only the direction is the invariant, then you could maintain 2^m bit-strings, each of length m. Each bit has a 0 or 1 depending on whether the edge (u,v) it corresponds to is u-->v or v<--u. Use the bit string to give direction to the undirected graph suggested above. You just need to generate all 2^m bit strings. Not very efficient... but you can't do better if you need to work with all possibilities.
You could use the bit string to construct a digraph. But, it would be more memory efficient at least to maintain only one bit-string per 'graph' rather than repeating the entire graph data structure with only directional changes. Record bit strings in a hash table: use each edge as a key and then bit value 0/1 depending on direction. Any graph traversal of one of the many possible digraphs D works on undirected G. Then in constant time you can check for incident (undirected) edges of a vertex, which are outgoing/incoming in D. So traversals can occur just as quickly by maintaining only 1 graph object and 1 bit hash table of size 2^m (rather than 2^m graph objects).

How to randomly pick a vertex or edge from graph of jGraphT

I have created a Graph with a set of edges I have (4000K Edges and 4K nodes).
Now I want to take 10% of the edges from the corpus to create a train and test data set.
I want to pick an edge in random, verify if the vertices of this edge has an edge with a random vertex. If so, I will remove that edge in the graph and also write that edge in a test file. So, that later I will predict the edges of the test file using some similarity function.
Logic is I am trying to predict A->C, given A->B and B->C.
Now the problem is, I cannot get a way to randomly pick an edge and randomly pick a vertex in JGraphT. My vertex names are some strings with random numbers.
Any one has a solution for this ?
There is a possibility. See the example first:
DirectedGraph<String, DefaultEdge> graph = new DefaultDirectedGraph<String, DefaultEdge>(DefaultEdge.class);
Object[] vertexSet = graph.vertexSet().toArray();
Object[] edgeSet = graph.edgeSet().toArray();
String someRndNode = (String) vertexSet [ getSomeRandomNumberBetween(0, vertexSet.length)];
DefaultEdge someRndEdge = (DefaultEdge) edgeSet [ getSomeRandomNumberBetween(0, edgeSet.length)];
You simply get the set of edges and nodes of your graph. Determine a random number based on the arrays. Get the stuff you need out of it.

Representing a graph where nodes are also weights

Consider a graph that has weights on each of its nodes instead of between two nodes. Therefore the cost of traveling to a node would be the weight of that node.
1- How can we represent this graph?
2- Is there a minimum spanning path algorithm for this type of graph (or could we modify an existing algorithm)?
For example, consider a matrix. What path, when traveling from a certain number to another, would produce a minimum sum? (Keep in mind the graph must be directed)
if one don't want to adjust existing algorithms and use edge oriented approaches, one could transform node weights to edge weights. For every incoming edge of node v, one would save the weight of v to the edge. Thats the representation.
well, with the approach of 1. this is now easy to do with well known algorithms like MST.
You could also represent the graph as wished and hold the weight at the node. The algorithm simply didn't use Weight w = edge.weight(); it would use Weight w = edge.target().weight()
simply done. no big adjustments are necessary.
if you have to use adjacency matrix, you need a second array with node weights and in adjacency matrix are just 0 - for no edge or 1 - for an edge.
hope that helped

Resources