Modeling a completely connected graph in Alloy - logic

I'm trying to get my feet wet with Alloy (also relatively new-ish to formal logic as well), and I'm trying to start with a completely connected graph of nodes.
sig Node {
adj : set Node
}
fact {
adj = ~adj -- symmetrical
no iden & adj -- no loops
all n : Node | Node in n.*adj -- connected
}
pred ex { }
run ex for exactly 3 Node
As you can see from the image, Nodes 0 and 1 aren't connected. I thought that my fact was enough to make it completely connected...but perhaps I missed something.

How about
adj = Node -> Node - iden
This basically says that adj contains all possible pairs of nodes, except identities (self-loops).
The reason why it is ok that Node1 and Node2 are not connected for your model is the last clause of your fact which constrains that for each node, all nodes are transitively reachable, but it seems to me that you want them to be immediately reachable. Alternatively to using my solution above, you can change
all n: Node | Node in n.*adj to all n: Node | (Node - n) in n.adj
to get the same effect.

Related

Generate all the leaf to leaf path in an n-array tree

Given an N-ary tree, I have to generate all the leaf to leaf paths in an n-array tree. The path should also denote the direction. As an example:
Tree:
1
/ \
2 6
/ \
3 4
/
5
Paths:
5 UP 3 UP 2 DOWN 4
4 UP 2 UP 1 DOWN 6
5 UP 3 UP 2 UP 1 DOWN 6
These paths can be in any order, but all paths need to be generated.
I kind of see the pattern:
looks like I have to do in order traversal and
need to save what I have seen so far.
However, can't really come up with an actual working algorithm.
Can anyone nudge me to the correct algorithm?
I am not looking for the actual implementation, just the pseudo code and the conceptual idea would be much appreciated.
The first thing I would do is to perform in-order traversal. As a result of this, we will accumulate all the leaves in the order from the leftmost to the rightmost nodes.(in you case this would be [5,4,6])
Along the way, I would certainly find the mapping between nodes and its parents so that we can perform dfs later. We can keep this mapping in HashMap(or its analogue). Apart from this, we will need to have the mapping between nodes and its priorities which we can compute from the result of the in-order traversal. In your example the in-order would be [5,3,2,4,1,6] and the list of priorities would be [0,1,2,3,4,5] respectively.
Here I assume that our node looks like(we may not have the mapping node -> parent a priori):
class TreeNode {
int val;
TreeNode[] nodes;
TreeNode(int x) {
val = x;
}
}
If we have n leaves, then we need to find n * (n - 1) / 2 paths. Obviously, if we have managed to find a path from leaf A to leaf B, then we can easily calculate the path from B to A. (by transforming UP -> DOWN and vice versa)
Then we start traversing over the array of leaves we computed earlier. For each leaf in the array we should be looking for paths to leaves which are situated to the right of the current one. (since we have already found the paths from the leftmost nodes to the current leaf)
To perform the dfs search, we should be going upwards and for each encountered node check whether we can go to its children. We should NOT go to a child whose priority is less than the priority of the current leaf. (doing so will lead us to the paths we already have) In addition to this, we should not visit nodes we have already visited along the way.
As we are performing dfs from some node, we can maintain a certain structure to keep the nodes(for instance, StringBuilder if you program in Java) we have come across so far. In our case, if we have reached leaf 4 from leaf 5, we accumulate the path = 5 UP 3 UP 2 DOWN 4. Since we have reached a leaf, we can discard the last visited node and proceed with dfs and the path = 5 UP 3 UP 2.
There might be a more advanced technique for solving this problem, but I think it is a good starting point. I hope this approach will help you out.
I didn't manage to create a solution without programming it out in Python. UNDER THE ASSUMPTION that I didn't overlook a corner case, my attempt goes like this:
In a depth-first search every node receives the down-paths, emits them (plus itself) if the node is a leaf or passes the down-paths to its children - the only thing to consider is that a leaf node is a starting point of a up-path, so these are input from the left to right children as well as returned to the parent node.
def print_leaf2leaf(root, path_down):
for st in path_down:
st.append(root)
if all([x is None for x in root.children]):
for st in path_down:
for n in st: print(n.d,end=" ")
print()
path_up = [[root]]
else:
path_up = []
for child in root.children:
path_up += child is not None and [st+[root] for st in print_root2root(child, path_down + path_up)] or []
for st in path_down:
st.pop()
return path_up
class node:
def __init__(self,d,*children):
self.d = d
self.children = children
## 1
## / \
## 2 6
## / \ /
## 3 4 7
## / / | \
## 5 8 9 10
five = node(5)
three = node(3,five)
four = node(4)
two = node(2,three,four)
eight = node(8)
nine = node(9)
ten = node(10)
seven = node(7,eight,nine,ten)
six = node(6,None,seven)
one = node(1,two,six)
print_leaf2leaf(one,[])

Graph Traversal using DFS

I am learning graph traversal from The Algorithm Design Manual by Steven S. Skiena. In his book, he has provided the code for traversing the graph using dfs. Below is the code.
dfs(graph *g, int v)
{
edgenode *p;
int y;
if (finished) return;
discovered[v] = TRUE;
time = time + 1;
entry_time[v] = time;
process_vertex_early(v);
p = g->edges[v];
while (p != NULL) {
/* temporary pointer */
/* successor vertex */
/* allow for search termination */
y = p->y;
if (discovered[y] == FALSE) {
parent[y] = v;
process_edge(v,y);
dfs(g,y);
}
else if ((!processed[y]) || (g->directed))
process_edge(v,y);
}
if (finished) return;
p = p->next;
}
process_vertex_late(v);
time = time + 1;
exit_time[v] = time;
processed[v] = TRUE;
}
In a undirected graph, it looks like below code is processing the edge twice (calling the method process_edge(v,y). One while traversing the vertex v and another at processing the vertex y) . So I have added the condition parent[v]!=y in else if ((!processed[y]) || (g->directed)). It processes the edge only once. However, I am not sure how to modify this code to work with the parallel edge and self-loop edge. The code should process the parallel edge and self-loop.
Short Answer:
Substitute your (parent[v]!=y) for (!processed[y]) instead of adding it to the condition.
Detailed Answer:
In my opinion there is a mistake in the implementation written in the book, which you discovered and fixed (except for parallel edges. More on that below). The implementation is supposed to be correct for both directed and undeirected graphs, with the distinction between them recorded in the g->directed boolean property.
In the book, just before the implementation the author writes:
The other important property of a depth-first search is that it partitions the
edges of an undirected graph into exactly two classes: tree edges and back edges. The
tree edges discover new vertices, and are those encoded in the parent relation. Back
edges are those whose other endpoint is an ancestor of the vertex being expanded,
so they point back into the tree.
So the condition (!processed[y]) is supposed to handle undirected graphs (as the condition (g->directed) is to handle directed graphs) by allowing the algorithm to process the edges that are back-edges and preventing it from re-process those that are tree edges (in the opposite direction). As you noticed, though, the tree-edges are treated as back-edges when read through the child with this condition so you should just replace this condition with your suggested (parent[v]!=y).
The condition (!processed[y]) will ALWAYS be true for an undirected graph when the algorithm reads it as long as there are no parallel edges (further details why this is true - *). If there are parallel edges - those parallel edges that are read after the first "copy" of them will yield false and the edge will not be processed, when it should be. Your suggested condition, however, will distinguish between tree-edges and the rest (back-edges, parallel edges and self-loops) and allow the algorithm to process only those that are not tree-edges in the opposite direction.
To refer to self-edges, they should be fine both with the new and old conditions: they are edges with y==v. Getting to them, y is discovered (because v is discovered before going through its edges), not processed (v is processed only as the last line - after going through its edges) and it is not v's parent (v is not its own parent).
*Going through v's edges, the algorithm reads this condition for y that has been discovered (so it doesn't go into the first conditional block). As quoted above (in the book there is a semi-proof for that as well which I will include at the end of this footnote), p is either a tree-edge or a back-edge. As y is discovered, it cannot be a tree-edge from v to y. It can be a back edge to an ancestor which means the call is in a recursion call that started processing this ancestor at some point, and so the ancestor's call has yet to reach the final line, marking it as processed (so it is still marked as not processed) and it can be a tree-edge from y to v, in which case the same situation holds - and y is still marked as not processed.
The semi-proof for every edge being a tree-edge or a back-edge:
Why can’t an edge go to a brother or cousin node instead of an ancestor?
All nodes reachable from a given vertex v are expanded before we finish with the
traversal from v, so such topologies are impossible for undirected graphs.
You are correct.
Quoting the book's (2nd edition) errata:
(*) Page 171, line -2 -- The dfs code has a bug, where each tree edge
is processed twice in undirected graphs. The test needs to be
strengthed to be:
else if (((!processed[y]) && (parent[v]!=y)) || (g->directed))
As for cycles - see here

Computing depth of each node in a "maximally packed" DAG

(Note: I thought about asking this on https://cstheory.stackexchange.com/, but decided my question is not theoretical enough -- it's about an algorithm. If there is a better Stack Exchange community for this post, I'm happy to listen!)
I'm using the terminology "starting node" to mean a node with no links into it, and "terminal node" to mean a node with no links out of it. So the following graph has starting nodes A and B and terminal nodes F and G:
I want to draw it with the following rules:
at least one starting node has a depth of 0.
links always point from top to bottom
nodes are packed vertically as closely as possible
Using those rules, depth of for each node is shown for the graph above. Can someone suggest an algorithm to compute the depth of each node that runs in less than O(n^2) time?
update:
I tweaked the graph to show that the DAG may contain starting and terminal nodes at different depths. (This was a case that I didn't consider in my original buggy answer.) I also switched terminology from "x coordinate" to "depth" in order to emphasize that this is about "graphing" and not "graphics".
Your x coordinate of a node corresponds to the longest way from any node without incomming edges to this node in question. For a DAG it can be calculated in O(N):
given DAG G:
calculate incomming_degree[v] for every v in G
initialize queue q={v with incomming_degree[v]==0}, x[v]=0 for every v in q
while(q not empty):
v=q.pop() #retreive and delete first element
for(w in neighbors of v):
incomming_degree[w]--
if(incomming_degree[w]==0): #no further way to w exists, evaluate
q.offer(w)
x[w]=x[v]+1
x stores the desired information.
Here's one solution which is essentially a two-pass depth-first tree walk. The first pass (traverseA) traces the DAG from the starting nodes (A and B in the O.P.'s example) until encountering terminal nodes (F and G in the example). It them marks them with the maximum depth as traced through the graph.
The second pass (traverseB) starts at the terminal nodes and traces back towards the starting nodes, marking each node along the way with the node's current value OR the previous node's value minus one, whichever is smaller if the node hasn't been visited yet:
function labelDAG() {
nodes.forEach(function(node) { node.depth = -1; }); // initialize
// find and mark terminal nodes
startingNodes().forEach(function(node) { traverseA(node, 0); });
// walk backwards from the terminal nodes
terminalNodes().forEach(function(node) { traverseB(node); });
dumpGraph();
};
function traverseA(node, depth) {
var targets = targetsOf(node);
if (targets.length === 0) {
// we're at a leaf (terminal) node -- set depth
node.depth = Math.max(node.depth, depth);
} else {
// traverse each subtree with depth = depth+1
targets.forEach(function(target) {
traverseA(target, depth+1);
});
};
};
// walk backwards from a terminal node, setting each source node's depth value
// along the way.
function traverseB(node) {
sourcesOf(node).forEach(function(source) {
if ((source.depth === -1) || (source.depth > node.x - 1)) {
// source has not yet been visited, or we found a longer path
// between terminal node and source node.
source.depth = node.depth - 1;
}
traverseB(source);
});
};

Maze algorithm that actually works

I've been working on trying to solve mazes and output the path from start to the end. No matter what I do though, it never really works 100%. It manages to backtrack trough the whole maze like it should and find the end... but actually outputting ONLY the path that it should take won't work. It works on some of the generated mazes, but not generally. It also includes some of the dead-ends.
The problem is that i've probably tried 10 different DFS algorithms online, but none of them works. It's very confusing that so many different sites seem to have algorithms that doesn't work, i've implemented them practically literally.
Would be very kind if someone could give an actual working pseudocode of how to write a simple maze solver using stack that shows the relevant path to take. After 20-25 hours of experimenting I don't think I will get anywhere anymore.
not exactly pseudocode, but it should work
define node: {int id}
define edge: {node a , b ; int weight (default=1)}
define listNeighbours:
input: node n
output: list of neighbours
define dfs:
input: list nodes, list edges, node start, node end
output: list path
bool visited[length(nodes)]
fill(visited , false)
list stack
add(stack , start)
visited[start.id] = true
while ! isEmpty(stack)
node c = first(stack)
if c.id == end.id
return stack
list neighbours = listNeighbours(c)
bool allVisited = true
node next
for node n in neighbours
if visited[n.id]
continue
else
allVisited = false
next = n
if allVisited
pop(stack)
else
push(stack , next)
return null
NOTE: ids of nodes are always <= the total number of nodes in the graph and unique in the graph

Bidirectional spanning tree

I came across this question from interviewstreet.com
Machines have once again attacked the kingdom of Xions. The kingdom
of Xions has N cities and N-1 bidirectional roads. The road network is
such that there is a unique path between any pair of cities.
Morpheus has the news that K Machines are planning to destroy the
whole kingdom. These Machines are initially living in K different
cities of the kingdom and anytime from now they can plan and launch an
attack. So he has asked Neo to destroy some of the roads to disrupt
the connection among Machines i.e after destroying those roads there
should not be any path between any two Machines.
Since the attack can be at any time from now, Neo has to do this task
as fast as possible. Each road in the kingdom takes certain time to
get destroyed and they can be destroyed only one at a time.
You need to write a program that tells Neo the minimum amount of time
he will require to disrupt the connection among machines.
Sample Input First line of the input contains two, space-separated
integers, N and K. Cities are numbered 0 to N-1. Then follow N-1
lines, each containing three, space-separated integers, x y z, which
means there is a bidirectional road connecting city x and city y, and
to destroy this road it takes z units of time. Then follow K lines
each containing an integer. Ith integer is the id of city in which ith
Machine is currently located.
Output Format Print in a single line the minimum time required to
disrupt the connection among Machines.
Sample Input
5 3
2 1 8
1 0 5
2 4 5
1 3 4
2
4
0
Sample Output
10
Explanation Neo can destroy the road connecting city 2 and city 4 of
weight 5 , and the road connecting city 0 and city 1 of weight 5. As
only one road can be destroyed at a time, the total minimum time taken
is 10 units of time. After destroying these roads none of the Machines
can reach other Machine via any path.
Constraints
2 <= N <= 100,000
2 <= K <= N
1 <= time to destroy a road <= 1000,000
Can someone give idea how to approach the solution.
The kingdom has N cities, N-1 edges and it's fully connected, therefore our kingdom is tree (in graph theory). At this picture you can see tree representation of your input graph in which Machines are represented by red vertices.
By the way you should consider all paths from the root vertex to all leaf nodes. So in every path you would have several red nodes and during removing edges you should take in account only neighboring red nodes. For example in path 0-10 there are two meaningfull pairs - (0,3) and (3,10). And you must remove exactly one node (not less, not more) from each path which connected vertices in pairs.
I hope this advice was helpful.
All the three answers will lead to correct solution but you can not achieve the solution within the time limit provided by interviewstreet.com. You have to think of some simple approach to solve this problem successfully.
HINT: start from the node where machine is present.
As said by others, a connected graph with N vertices and N-1 edges is a tree.
This kind of problem asks for a greedy solution; I'd go for a modification of Kruskal's algorithm:
Start with a set of N components - 1 for every node (city). Keep track of which components contain a machine-occupied city.
Take 1 edge (road) at a time, order by descending weight (starting with roads most costly to destroy). For this edge (which necessarily connects two components - the graph is a tree):
if both neigboring components contain a machine-occupied city, this road must be destroyed, mark it as such
otherwise, merge the neigboring components into one. If one of them contained a machine-occupied city, so does the merged component.
When you're done with all edges, return the sum of costs for the destroyed roads.
Complexity will be the same as Kruskal's algorithm, that is, almost linear for well chosen data structure and sorting method.
pjotr has a correct answer (though not quite asymptotically optimal), but this statement
This kind of problem asks for a greedy solution
really requires proof, as in the real world (as distinguished from competitive programming), there are several problems of this “kind” for which the greedy solution is not optimal (e.g., this very same problem in general graphs, which is called multiterminal cut and is NP-hard). In this case, proof consists of verifying the matroid axioms. Let a set of edges A &subseteq; E be independent if the graph (V, E &setminus; A) has exactly |A| + 1 connected components containing at least one machine.
Independence of the empty set. Trivial.
Hereditary property. Let A be an independent set. Every edge e &in; A joins two connected components of the graph (V, E &setminus; A), and every connected component contains at least one machine. In putting e back in the graph, the number of connected components containing at least one machine decreases by 1, so A &setminus; {e} is also independent.
Augmentation property. Let A and B be independent sets with |A| < |B|. Since (V, E &setminus; B) has more connected components than (V, E &setminus; A), there exists by the pigeonhole principle a pair of machines u, v such that u and v are disconnected by B but not by A. Since there is exactly one path from u to v, B contains at least one edge e on this path, and A cannot contain e. The removal of A ∪ {e} induces one more connected component containing at least one machine than A, so A ∪ {e} is independent, as required.
Start performing a DFS from either of the machine nodes. Also, keep track of the edge with min weight encountered so far. As soon as you find the next node which also contains a machine, delete the min edge recorded so far. Start DFS from this new node now.
Repeat until you have found all nodes where the machines exists.
Should be of the O(N) that way !!
I write some code, and pasted all the tests.
#include <iostream>
#include<algorithm>
using namespace std;
class Line {
public:
Line(){
begin=0;end=0; weight=0;
}
int begin;int end;int weight;
bool operator<(const Line& _l)const {
return weight>_l.weight;
}
};
class Point{
public:
Point(){
pre=0;machine=false;
}
int pre;
bool machine;
};
void DP_Matrix();
void outputLines(Line* lines,Point* points,int N);
int main() {
DP_Matrix();
system("pause");
return 0;
}
int FMSFind(Point* trees,int x){
int r=x;
while(trees[r].pre!=r)
r=trees[r].pre;
int i=x;int j;
while(i!=r) {
j=trees[i].pre;
trees[i].pre=r;
i=j;
}
return r;
}
void DP_Matrix(){
int N,K,machine_index;scanf("%d%d",&N,&K);
Line* lines=new Line[100000];
Point* points=new Point[100000];
N--;
for(int i=0;i<N;i++) {
scanf("%d%d%d",&lines[i].begin,&lines[i].end,&lines[i].weight);
points[i].pre=i;
}
points[N].pre=N;
for(int i=0;i<K;i++) {
scanf("%d",&machine_index);
points[machine_index].machine=true;
}
long long finalRes=0;
for(int i=0;i<N;i++) {
int bP=FMSFind(points,lines[i].begin);
int eP=FMSFind(points,lines[i].end);
if(points[bP].machine&&points[eP].machine){
finalRes+=lines[i].weight;
}
else{
points[bP].pre=eP;
points[eP].machine=points[bP].machine||points[eP].machine;
points[bP].machine=points[eP].machine;
}
}
cout<<finalRes<<endl;
delete[] lines;
delete[] points;
}
void outputLines(Line* lines,Point* points,int N){
printf("\nLines:\n");
for(int i=0;i<N;i++){
printf("%d\t%d\t%d\n",lines[i].begin,lines[i].end,lines[i].weight);
}
printf("\nPoints:\n");
for(int i=0;i<=N;i++){
printf("%d\t%d\t%d\n",i,points[i].machine,points[i].pre);
}
}

Resources