Mathematica : duplicate edges - wolfram-mathematica

I am trying to generate a graph from an adjacency list, but Mathematica doesn't want to plot my graph because of multiple edges i think.
This is my script :
Needs["GraphUtilities`"]
data = Import["adj_matrix.txt", "Table"];
data2 = Flatten[Table[{data[[i, 1]] \[UndirectedEdge] data[[i, 2]]}, {i, 1,
Length[data]}]];
graph1 = Graph[data2]
The error i get is :
Graph::supp: Mixed graphs and multigraphs are not supported.
I do not have any "proper" duplicates in my list, the only type of duplicates that appear are 1->2 and 2->1.
I would like to know how to delete these "duplicates" from my list.

You can directly convert an adjacency matrix to a Graph using AdjacencyGraph[]. This is probably the simplest solution:
AdjacencyGraph[data]
If your matrix contains other elements than 0 and 1, use
AdjacencyGraph#Clip[data]
To filter out duplicates from the edge list of an undirected graph, use
Union[Sort /# edgeList]

Related

perfect hash function for random integer

Here's the problem:
X is a positive integer (include 0) set which has n different elements I know in advance. All of them is less equal than m. And I want to have an occ-free hash function as simple as possible to map them to 0-n-1.
For example:
X = [31,223,121,100,123,71], so n = 6, m = 223.
I want to find a hash function to map them to [0, 1, 2, 3, 4, 5].
If mapping to 0-n-1 is too difficult, then how to mapping X to a small range is also a problem.
Finding such a function is not too difficult, but to be simple and easy to be generated is hard.
It's better to preserve the order of the X.
Any clues?
My favorite perfect hash is pretty easy.
The hash function you generate has the form:
hash = table1[h1(key)%N] + table2[h2(key)%N]
h1 and h2 are randomly generated hash functions. In your case, you can generate random constants and then have h1(key)=key*C1/m and h2(key)=key*C2/m or something similarly simple
To generated the perfect hash:
Generate random constants C1 and C2
Imagine the bipartite graph, with table1 slots and table2 slots as vertices and an edge for each key between table1[h1(key)%N] and table2[h2(key)%N]. Run a DFS to see if the graph is acyclic. If not, go back to step 1.
Now that you have an acyclic graph, start at any key/edge in each connected component, and set its slots in table1 and table2 however you like to give it whatever hash you like.
Traverse the tree starting at the vertices adjacent to the edge you just set. For every edge you traverse, one of its slots will already be set. Set the other one to make the hash value come out however you like.
That's it. All of steps (2), (3) and (4) can be combined into a single DFS traversal pretty easily.
The complete description and analysis is in this paper.

how to generate a maze using a binary matrix representation?

I'm suppose to generate a maze using a binary matrix
when a 0 represents empty cell
and 1 a wall
I tried to use the DFS algorithm, the problem is the DFS refers to cells and walls between them(each cell has at most four walls)
" then selects a random neighbouring cell that has not yet been visited. The computer removes the 'wall' between the two cells and.."
I don't understand to analogy to the representation I've been asked to implement
anyone has any idea?
When asked to make a grid, I'd start by making a multi-dimensional array.
Have the outer array contain each row of your grid, and each nested array be the columns.
Depending if each cell needs to remember being visited, each slot of the array can contain a simple class or struct (depending on your language of choice). Else, they can simply contain an int or a bool.
A simple example could be:
var grid = [
[1, 1, 1],
[1, 0, 1],
[1, 1, 1]
];
Representing an empty cell in the middle, surrounded by walls.
The idea is to construct a pattern of cells, then build wall between them, but not when it has a edge of DFS tree.
Example DFS run (2D case, edge removed, can be inferred from order of nodes):
O
O
O
O
OO
OO
OO
(this branch is stuck so start a new one)
OOO
OO
...
OOO
OOO
OOO
Now construct the maze:
OXSOO
OXOXO
OOOXO
XXXXO
EOOOO
O -> cell
X -> wall
S -> start
E -> end
The wall can be either a block or just a plane, the topology is same.

VF2 algorithm - implementation

I have a problem with the VF2 algorithm implementation. Everything seems to be working perfectly in many cases, however there is a problem I cannot solve.
The algorithm does not work on the example below. In this example, we are comparing two identical graphs (see image below). Starting vertex is 0.
The set P, that is calculated inside s0, stores the powerset of all pairs of vertices.
Below is a pseudocode included in the publications about VF2 on which I based my implementation.
http://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=B51AD0DAEDF60D6C8AB589A39A570257?doi=10.1.1.101.5342&rep=rep1&type=pdf
http://www.icst.pku.edu.cn/intro/leizou/teaching/2012-autumn/papers/part2/VF2%20A%20%28sub%29Graph%20Isomorphism%20Algorithm%20For%20Matching%20Large%20Graphs.pdf
Comments on the right side of /* describe the way I understand the code:
I'm not sure if creating the P() set is valid as described below. Powersets of pairs are iterated in lexicographical order by first and then second value of pair.
PROCEDURE Match(s)
INPUT: an intermediate state s; the initial state s0 has M(s0)=empty
OUTPUT: the mappings between the two graphs
IF M(s) covers all the nodes of G2 THEN
OUTPUT M(s)
ELSE
Compute the set P(s) of the pairs candidate for inclusion in M(s)
/*by powerset of all succesors from already matched M(s) if not empty or
/*predestors to already matched M(s) if not empty
/*or all possible not included vertices in M(s)
FOREACH (n, m)∈ P(s)
IF F(s, n, m) THEN
Compute the state s ́ obtained by adding (n, m) to M(s)
/*add n to M1(s), exclude from T1(s)
/*add m to M2(s), exclude from T2(s)
/*M1(s) is now M1(s'), other structures belong to s' too
CALL Match(s′)
END IF
END FOREACH
Restore data structures
/*Return all structures as from before foreach
END IF
END PROCEDURE
When the algorithm goes to s4, when returing from the function, it looses information about good vertices match.
It results in searching the subgraph-isomorphism ({(0,0),(1,1),(2,2),(5,3),(6,4)}) - even though the graphs are isomorphic.
What am I doing wrong here?
I think that to know your question "what am I doing wrong here", it is necessary to include some of your code here. You re-implemented the code yourself, based on the pseudo-code presented in the paper? or you were doing the matching with the help of some graph-processing packages?
For me I didn't have time to dig in the details, but I work with graphs as well, so I tried with networkx (a Python package) and Boost 1.55.0 library (very extensive C++ lib for graph). Your example and another example of a graph with 1000 nodes, 1500 edges return the correct matching (the trivial case of matching a graph with itself).
import networkx as nx
G1 = nx.Graph()
G2 = nx.Graph()
G1.clear()
G2.clear()
G1.add_nodes_from(range(0,7))
G2.add_nodes_from(range(0,7))
G1.add_edges_from([(0,1), (1,2), (2,3), (3,4), (2,5), (5,6)])
G2.add_edges_from([(0,1), (1,2), (2,3), (3,4), (2,5), (5,6)])
from networkx.algorithms import isomorphism
GM = isomorphism.GraphMatcher(G2,G1)
print GM.is_isomorphic()
GM.mapping
True
Out[39]:
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6}

Sort eigenvalue matrix with eigenvector matrix

I have N eigenvalues in column vector form.
Thus there are N eigenvectors corresponding to these eigenvalues, forming an eigenvector matrix.
Now, the problem I am working on requires me to sort the eigenvalues column vector in descending order. How do I sort the eigenvectors matrix in the same order as their eigenvalues in order to preserve correspondence?
For example,
m = RandomReal[{0, 1}, {5, 5}];
{evals, evecs} = Eigensystem[m];
SortBy[Transpose[{evals, evecs}], First]
or if you want them in the same form, replace the last line by
Transpose#SortBy[Transpose[{evals, evecs}], First]
EDIT: while I used {evals,evecs}=Eigensystem[m], that's not necessary. I could just have used s=Eigensystem[m] and then used s wherever I currently have {evals,evecs}.
While #acl and #yoda's ways of sorting (i.e. pairing the list elements then sorting together) is easy and commonly used, I'd like to show another generic method to easily sort an arbitrary number of lists based on one particular list (list1):
oo = Ordering[list1]; (* this finds the sorting order of list1 *)
list1[[oo]]
list2[[oo]]
list3[[oo]] (* these order some other lists in the same way *)
You can use the Sort function to sort the eigensystem according to the eigenvalues.
mat = (#*Transpose##) &#RandomReal[NormalDistribution[], {4, 4}];
eigsys = Sort#Transpose#Eigensystem[mat];
Sort's default behavior is to sort by the first column.
Using Mathematica:
matrix = RandomReal[{0, 1}, {4, 4}];
{evals, evecs} = Chop[Transpose[Sort[Transpose[Eigensystem[matrix]]]]];
OutPut:
evals
{-0.296769, 0.187003, 0.52714, 2.00376}
evecs
{{-0.412673,0.844056,-0.0718614,-0.334823},
{-0.370973, -0.472126, 0.76248, 0.241042},
{-0.253163, 0.1719, -0.786782, 0.536034},
{0.557741, 0.381364, 0.65039, 0.347102}}

For every vertex in a graph, find all vertices within a distance d

In my particular case, the graph is represented as an adjacency list and is undirected and sparse, n can be in the millions, and d is 3. Calculating A^d (where A is the adjacency matrix) and picking out the non-zero entries works, but I'd like something that doesn't involve matrix multiplication. A breadth-first search on every vertex is also an option, but it is slow.
def find_d(graph, start, st, d=0):
if d == 0:
st.add(start)
else:
st.add(start)
for edge in graph[start]:
find_d(graph, edge, st, d-1)
return st
graph = { 1 : [2, 3],
2 : [1, 4, 5, 6],
3 : [1, 4],
4 : [2, 3, 5],
5 : [2, 4, 6],
6 : [2, 5]
}
print find_d(graph, 1, set(), 2)
Let's say that we have a function verticesWithin(d,x) that finds all vertices within distance d of vertex x.
One good strategy for a problem such as this, to expose caching/memoisation opportunities, is to ask the question: How are the subproblems of this problem related to each other?
In this case, we can see that verticesWithin(d,x) if d >= 1 is the union of vertices(d-1,y[i]) for all i within range, where y=verticesWithin(1,x). If d == 0 then it's simply {x}. (I'm assuming that a vertex is deemed to be of distance 0 from itself.)
In practice you'll want to look at the adjacency list for the case d == 1, rather than using that relation, to avoid an infinite loop. You'll also want to avoid the redundancy of considering x itself as a member of y.
Also, if the return type of verticesWithin(d,x) is changed from a simple list or set, to a list of d sets representing increasing distance from x, then
verticesWithin(d,x) = init(verticesWithin(d+1,x))
where init is the function that yields all elements of a list except the last one. Obviously this would be a non-terminating recursive relation if transcribed literally into code, so you have to be a little bit clever about how you implement it.
Equipped with these relations between the subproblems, we can now cache the results of verticesWithin, and use these cached results to avoid performing redundant traversals (albeit at the cost of performing some set operations - I'm not entirely sure that this is a win). I'll leave it as an exercise to fill in the implementation details.
You already mention the option of calculating A^d, but this is much, much more than you need (as you already remark).
There is, however, a much cheaper way of using this idea. Suppose you have a (column) vector v of zeros and ones, representing a set of vertices. The vector w := A v now has a one at every node that can be reached from the starting node in exactly one step. Iterating, u := A w has a one for every node you can reach from the starting node in exactly two steps, etc.
For d=3, you could do the following (MATLAB pseudo-code):
v = j'th unit vector
w = v
for i = (1:d)
v = A*v
w = w + v
end
the vector w now has a positive entry for each node that can be accessed from the jth node in at most d steps.
Breadth first search starting with the given vertex is an optimal solution in this case. You will find all the vertices that within the distance d, and you will never even visit any vertices with distance >= d + 2.
Here is recursive code, although recursion can be easily done away with if so desired by using a queue.
// Returns a Set
Set<Node> getNodesWithinDist(Node x, int d)
{
Set<Node> s = new HashSet<Node>(); // our return value
if (d == 0) {
s.add(x);
} else {
for (Node y: adjList(x)) {
s.addAll(getNodesWithinDist(y,d-1);
}
}
return s;
}

Resources