How do I constrain connected vertices to share a single edge? - graphviz

Because of the way that information is being generated, I results that look like this:
digraph "A" {
"a1" -> "a2";
"a2" -> "a1";
"a1" -> "a2";
"a2" -> "a1";
}
What I would prefer to see, is:
digraph "A" {
"a1" -> "a2"[dir=both];
}
Is there a way to tell the entire digraph to merge edges,
and create bidirectional edges where possible?
I'd like to keep the data as generated, but add a few lines to create the second image.

That's essentially what concentrate is for.
Simply add the following line to your graph, at the beginning or the end:
concentrate=true

As already answerd by marapet the answer to your case is concentrate. However there is a completely different answer to a slightly different problem which I want to add here for completeness. If you want to merge directed edges only you may use the keyword strict.
strict digraph "A" {
"a1" -> "a2";
"a2" -> "a1";
"a1" -> "a2";
"a2" -> "a1";
}

Related

Graphviz: Independent tree branch

I did this on GVEdit. I want to know if it's possible to make every branch independent? Which means every answer in a independent case.
Take this for example:
digraph G{
"Is it red" -> "no answer"[label="yes"]
"Is it red" -> "Is it sweet?"[label="no"]
"Is it sweet?" -> "apple"[label="yes"]
"Is it sweet?" -> "no answer"[label="no"]
}
Print:
And I expected to print:
Last question, I tried to save my tree as png file on GVEdit, but don't know how to do it. My cmd is not working cause it cannot find dot file. Thanks!
Using different id's for the nodes having the same labels should do the trick:
digraph G{
na1[label="no answer"];
"Is it red" -> na1[label="yes"]
"Is it red" -> "Is it sweet?"[label="no"]
"Is it sweet?" -> "apple"[label="yes"]
na2[label="no answer"];
"Is it sweet?" -> na2[label="no"]
}

ArangoDB 3.2 traversal: exclude edge collection

I am doing an AQL traversal with ArangoDB 3.2 in which I retrieve the nodes connected to my vertexCollection like this:
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "global", bfs:true}
RETURN v._id
and now I want to skip the nodes from paths where a particular edge collection is used. I know I can filter for particular attributes in lists, like FILTER p.edges[*].type ALL == 'whatever' but I do not find how to apply this into IS_SAME_COLLECTION() to filter by collection.
I discard the option of specifying exactly the edgeCollection in the traversal instead of the GRAPH because it's just one particular edgeCollection that I want to skip vs. many that I want to go through.
I don't know whether there is already an implementation for 'skip edge collection' or something like that in a graph traversal, so far I could not find it.
Note:
I tried to filter like this
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "global", bfs:true}
FILTER NOT IS_SAME_COLLECTION('edgeToSkip', e._id)
RETURN v._id
But here I simply skip the nodes directly connected with edge 'edgeToSkip' but not all nodes within the path where 'edgeToSkip' is present. So I need, not only to exclude that particular edge, but stop traversing when it is found.
Thanks
UPDATE:
I found a workaround, basically I gather all edges present in a 'path' and then filter out if the edge I want to skip is in the 'path'. Note I change from uniqeVertices: "global" to uniqueVertices: "path".
.
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "path", bfs:true}
# collect edge names (collection name) in the current path
LET ids = (
FOR edge IN p.edges
RETURN PARSE_IDENTIFIER(edge)["collection"]
)
# filter out if edge name (edgeToSkip) is present
FILTER 'edgeToSkip' NOT IN ids
RETURN v._id
This way, once the edgeToSkip is found in the path, no vertex is returned, but vertices before the 'edgeToSkip' yes
If the graph is like this:
vertexA --edge1--> vertexB --edge2--> vertexC --edgeToSkip--> vertexD --edge3--> vertexE
Will return:
vertexA, vertexB and vertexC (but not vertexD and vertexE)
I found a workaround, basically I gather all edges present in a 'path' and then filter out if the edge I want to skip is in the 'path'. Note I change from uniqeVertices: "global" to uniqueVertices: "path".
.
For v, e, p IN 1..10 ANY vertexCollection GRAPH myGraph OPTIONS {uniqueVertices: "path", bfs:true}
# collect edge names (collection name) in the current path
LET ids = (
FOR edge IN p.edges
RETURN PARSE_IDENTIFIER(edge)["collection"]
)
# filter out if edge name (edgeToSkip) is present
FILTER 'edgeToSkip' NOT IN ids
RETURN v._id
This way, once the edgeToSkip is found in the path, no vertex is returned, but vertices before the 'edgeToSkip' yes
If the graph is like this:
vertexA --edge1--> vertexB --edge2--> vertexC --edgeToSkip--> vertexD --edge3--> vertexE
Will return:
vertexA, vertexB and vertexC (but not vertexD and vertexE)

Find the longest chaining list?

I have a lot of objects. Some object can produce a chaining list, and all objects have a chaining continuation on condition. A exemple will explain more. Let's say I have this two objects :
[
{
"name": "ObjectA",
"produce": "ChainA",
"continuations": [
{ "ChainB": "ChainC" },
{ "ChainC": "ChainC" }
]
}
{
"name": "ObjectB",
"produce": null,
"continuations": [
{ "ChainA": "ChainB" }
]
}
]
I need to find the list :
ChainA (ObjectA) => ChainB (ObjectB) => ChainC (ObjectA) => ChainC (ObjectA)
I just can't find a better way that looping over and over again. Some of you have an idea ?
Thanks
This problem is NP-complete because if you had an efficient algorithm to solve it, then you could solve https://en.wikipedia.org/wiki/Longest_path_problem. So it is pretty hopeless.
Here is the reduction. Given a directed graph G, label the edges as objects and label the vertices as chains. Each "object" (edge) produces the "chain" that is the vertex it goes to. Each "object" (edge) has a single continuation, from the source "chain" (vertex) to the target "chain" (vertex).
Now apply the hypothetical algorithm. The longest chaining list will be the edges of the desired longest path for G.

Porter Stemmer, Step 1b

Similar question to this [1]porter stemming algorithm implementation question?, but expanded.
Basically, step1b is defined as:
Step1b
`(m>0) EED -> EE feed -> feed
agreed -> agree
(*v*) ED -> plastered -> plaster
bled -> bled
(*v*) ING -> motoring -> motor
sing -> sing `
My question is why does feed stem to feed and not fe? All the online Porter Stemmer's I've tried online stems to feed, but from what I see, it should stem to fe.
My train of thought is:
`feed` does not pass through `(m>0) EED -> EE` as measure of `feed` minus suffix `eed` is `m(f)`, hence `=0`
`feed` will pass through `(*v*) ED ->`, as there is a vowel in the stem `fe` once the suffix `ed` is removed. So will stem at this point to `fe`
Can someone explain to me how online Porter Stemmers manage to stem to feed?
Thanks.
It's because "feed" doesn't have a VC (vowel/consonant) combination, therefore m = 0. To remove the "ed" suffix, m > 0 (check the conditions for each step).
The rules for removing a suffix will be given in the form
(condition) S1 -> S2
This means that if a word ends with the suffix S1, and the stem before S1 satisfies the given condition, S1 is replaced by S2. The condition is usually given in terms of m, e.g.
(m > 1) EMENT ->
Here S1 is `EMENT' and S2 is null. This would map REPLACEMENT to REPLAC, since REPLAC is a word part for which m = 2.
now, in your example :
(m>0) EED -> EE feed -> feed
before 'EED', are there vowel(s) followed by constant(s), repeated more than zero time??
answer is no, befer 'EED' is "F", there are not vowel(s) followed by constant(s)
In feed m refers to vowel,consonant pair. there is no such pair.
But in agreed "VC" is ag. Hence it is replaced by agree. The condition is m>0.
Here m=0.
It's really sad that nobody here actually read the question. This is why feed doesn't get stemmed to fe by rule 2 of step 1b:
The definition of the algorithm states:
In a set of rules written beneath each other, only one is obeyed, and this
will be the one with the longest matching S1 for the given word.
It isn't clearly statet that the conditions are always ignored here, but they are. So feed does match to the first rule (but it isn't applied since the condition isn't met) and therefore the rest of the rules in 1b are ignored.
The code would approximately look like this:
// 1b
if(word.ends_with("eed")) { // (m > 0) EED -> EE
mval = getMvalueOfStem();
if(mval > 0) {
word.erase("d");
}
}
else if(word.ends_with("ed")) { // (*v*) ED -> NULL
if(containsVowel(wordStem) {
word.erase("ed");
}
}
else if(word.ends_with("ing")) { // (*v*) ING -> NULL
if(containsVowel(wordStem) {
word.erase("ing");
}
}
The important things here are the else ifs.

Only show unique edges in graphviz

I have an input file with about ~5000 lines and 1 to 9 nodes per line.
Many edges are not unique and I would like to only show the unique ones.
A more simple example.
graph {
a -- b
a -- b
a -- b
}
Yields
Is there a way to make the above graph yield something like
I know I could change the sample input to
graph {
a -- b
}
But it would not be easy to do that for my real input.
There actually is a way: Use the strict keyword:
strict graph G {
a -- b [label="First"];
a -- b [label="Second"];
a -- b [label="Third"];
}
Result:
Without strict, all three edges would be shown. Note that it only takes the first edge's attributes, contrary to what the documentation suggests.
Try strict:
strict graph {
a -- b
a -- b
a -- b
}
This yields
and should work for any size of graph.
In case you want to get a clean file, which doesn't contain any of the duplicate edges, you can use the graph processing tool gvpr.
Here is a snippet, which does just that:
BEG_G { graph_t g = graph($G.name,"U") }
E {
node_t h = clone(g,$.head);
node_t t = clone(g,$.tail);
if(isEdge(t,h,"")==NULL){
edge_t e = clone(g,$);
}
}
END_G { $O = g; }
save this as something like gvpr_rm_dupl_edges and run $ gvpr -f gvpr_rm_dupl_edges input.dot -o output.dot. gvpr comes preinstalled with graphviz.
In case of directed graphs, change the "U" in the beginning of the code snippet to "D"
I wrote this snippet for a simple graph, without sub-graphs. It might not work on something more sophisticated.

Resources