Testing graph bipartitness - java

I wrote an algorithms for testing graph bipartitness for Graph Algorithms course on edX (initially available on Coursera) and it fails on one of their test cases.
I gave it a thought and cannot find so far what might I be missing, I use BFS traversal to color nodes to test for bipartitness, it works on a few simple test cases and on 17 of 28 test cases on edX.
private static final int WHITE = -1;
private static final int BLACK = -2;
private static final int START_INDEX = 0;
static boolean isBipartite(ArrayList<Integer>[] adj) { // an array of lists of neighbors
int[] colors = new int[adj.length];
boolean[] visited = new boolean[adj.length];
colors[START_INDEX] = WHITE;
Queue<Integer> queue = new LinkedList<>();
// start with some node
queue.add(START_INDEX);
while (!queue.isEmpty()) {
int node = queue.poll();
ArrayList<Integer> neighbors = adj[node];
for (int neighbor : neighbors) {
if (!visited[neighbor]) {
if (node != neighbor) {
// add for traversal and color with an opposite color
queue.add(neighbor);
colors[neighbor] = colors[node] == WHITE ? BLACK : WHITE;
} else {
// self cycle will always be odd
return false;
}
} else {
// return immediately if encountered an already colored node
// with the same color, there is an odd cycle
if (colors[node] == colors[neighbor]) {
return false;
}
}
}
visited[node] = true;
}
// final check of u and v colors for all edges
for (int u = 0; u < adj.length; u++) {
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u].get(i);
if (colors[u] == colors[v]) {
return false;
}
}
}
return true;
}
Any suggesting what could I be missing in my algorithm?
Also without the final check my algorithm would fail on the 3rd test case out of 28 (I do not see the inputs), even though I don't understand why - I should already be finding the odd cycles in the main for loop.
Please help.
Some of the sample graphs I tested myself, the 1st is not bipartite, the 2nd is bipartite.

As has been noted in the comments, you assume that every node is reachable from the starting node. The good news is that this is quite easy to fix. Define an enum Colors of three values: NoColor, Black, and White. The pseudocode goes as follows:
Input: graph G with nodes integers from 0 to n - 1
Initialise array colors of length n with all values set to NoColor;
for each `i` from `0` to `n - 1`, do {
if colors[i] = NoColor then {
Initialise q to an empty queue (or stack - whatever floats your boat);
push i onto queue;
colors[i] <- Black;
while q is not empty do {
pop k off of q;
for each neighbour i of k such that colors[i] = NoColor do
colors[i] <- the opposite color of colors[k];
push i onto q;
}
}
}
}
This gives you the 2-coloring, if the coloring exists. In this case, you'll want to verify that it is in fact a 2-coloring to check if the graph is bipartite.

Related

How do I calculate the time complexity of my method?

I need to get something on this format:
C(N)=2C(N/2)+N
C(N)=O(N〖log〗_2 N)
But I don't understand how the values work because my method has a loop that normaly wont pass through all vertexs and a loop inside of it that normally goes all the way but the number of iterations varies a lot.
...
private static boolean bfs(int[] pathArray, int[] dist) {
//Will make sure nodes are checked in the right order
LinkedList<Integer> queue = new LinkedList<>();
//Starts the array dist[] that has the distance of the vertex to the 1st Critical point; and the array path[] that has the previous vertex;
Arrays.fill(dist, -1);
Arrays.fill(pathArray, -1);
//Make CriticalPoint1 the starting point of the bfs
dist[criticalPoint1] = 0;
queue.add(criticalPoint1);
int adj;
int k;
//Goes to all the adjacent vertexes and sees if any of them are the destination, if they are not adds them to the queue to check their adjacent vertexes
while (!queue.isEmpty()) {
// k is the current vertex
k = queue.remove();
for (Graph.Edge<Integer> allAdjIterator : graph.getVertex(k).getAdjacencies()) {
// adj is the current adjacent vertex
adj = allAdjIterator.getIdAdj();
if (dist[adj]==-1 && !allPassedEdges.contains(graph.getEdge(k,adj))) {
dist[adj] = dist[k] + 1;
pathArray[adj] = k;
queue.add(adj);
if (adj == criticalPoint2) { return true; }
}
}
}
//Critical points aren't connected
return false;
}
...

Graph Colouring program

I've been asked to create a Java program, wherein I accept a predefined number of vertices first, and then all the edges which exist in the graph as number pairs.
My code is supposed to accept the edges, create the 'graph' and color all the vertices.
My problem is with the coloring. The method 'setColor' is supposed to accept the degree of the graph each time it is called. The getBiggestVertex method is supposed to return the vertex to be coloured. It is then colored.
For some reason however, when I display the colors of the vertices, I constantly get either 0 or 1 or -1.
I'm unable to figure out why I am getting this output, could someone please help?
Graph Class:
import java.util.ArrayList;
import java.util.Scanner;
public class Graph {
ArrayList <Vertex> vertices = new ArrayList<Vertex>();
public Graph(){
Scanner sc = new Scanner(System.in);
int noOfVertices = sc.nextInt();
for(int i = 0; i <noOfVertices; i++){
addVertex();
}
String input = sc.next();
while(!input.equals("-1")){
String vertex [] = input.split(",");
addEdge(vertices.get(Integer.parseInt(vertex[0])), vertices.get(Integer.parseInt(vertex[1])));
input = sc.next();
}
for(int i = 0; i<vertices.size(); i++){
getBiggestVertex().setColor(vertices.size());
}
}
public Vertex getBiggestVertex(){
Vertex bVertex = new Vertex(-1);
for(int i = 0; i < vertices.size(); i++){
Vertex v = vertices.get(i);
if(v.colour ==-1){
if(v.getDegree() > bVertex.getDegree()){
bVertex = v;
} else if(v.getDegree() == bVertex.getDegree()){
if(v.vertexNumber < bVertex.vertexNumber){
bVertex = v;
}
} else if(v.getDegree() < bVertex.getDegree()){
}
}
}
return bVertex;
}
public void addVertex(){
vertices.add(new Vertex(vertices.size()));
}
public Vertex getVertex(int index){
return vertices.get(index);
}
public void addEdge(Vertex v1, Vertex v2){
v1.addAdjacency(v2);
v2.addAdjacency(v1);
}
}
Vertex Class:
import java.util.LinkedList;
public class Vertex {
int vertexNumber, colour;
LinkedList <Vertex> adjacencies = new LinkedList<Vertex>();
public Vertex(int vertexNum){
vertexNumber = vertexNum;
colour = -1;
}
public void addAdjacency(Vertex v){
adjacencies.add(v);
}
public boolean isAdjacent(Vertex v){
boolean adj = false;
for(int i = 0; i < adjacencies.size(); i++){
if(adjacencies.get(i) == v){
adj = true;
}
}
return adj;
}
public int getDegree(){
return adjacencies.size();
}
public void setColor(int degree){
int [] used = new int[degree];
for(int i = 0; i < adjacencies.size(); i++){
int c = adjacencies.get(i).colour;
System.out.println("Color of " + i + " = " + c);
used[c+1] = 1;
}
int unusedColor = 0;
while(used[unusedColor] == 1){
unusedColor ++;
}
colour = unusedColor;
}
}
I assume that -1 represents a vertex color not yet defined.
There are several issues with your code, most of which center around setColor method:
When checking the colors of adjacent vertices, the range of color codes is shifted by 1 to serve as indices into the usage marker array used. However, after having visited all neighbours the first color you test for is 0.
This process colors a vertex that only has uncolored neighbours with 1.
In case all neighbours have been colored, the assigned color will be 0.
Moreover in getBiggestVertex, the condition (v.vertexNumber < bVertex.vertexNumber) will never fire for vertices with an outdegree of 0 when all remaining vertices without assigned colors have outdegree 0 ( bVertex is initialised with the minimal vertex number of -1 and will never be reassigned ).
That means in particular that you may produce paths of vertices of the same color. Notably the following graph will be given an invalid colouring :
4,5
4,6
4,7
4,3
3,8
3,9
3,2
2,10
2,1
9,2
results in the colouring
c(1) = -1
c(2) = 1
c(3) = 1
c(4) = 1
c(5) = -1
c(6) = -1
c(7) = -1
c(8) = -1
c(9) = 0
c(10) = -1
c(11) = -1
where node 3 would need a new color 2 and -1 is an invalid color (which may be construed ex post as valid, of course).
Rectify the code by
maintaining bidirectional adjacencies (so a,b implies that a is adjacent to b and vice versa )
writing used[c] instead of used[c+1].
or check the colors of predecessor vertices as well.
In addition to the flawed color assignment, consider the following suggestions to improve your code:
The max degree is a property of the graph and thus should be a property of the graph class. Thus you do not need to allocate the worst case degree of the current number of vertices - 1 for the used array in setColor.
The node(s) with the highest degree in the graph need not be recomputed from scratch on every use but may be a property of the graph class as well
Taking the previous advice one step further, you may sort the vertices of the graph by decreasing degree before the colouring process storing this list. The should relieve you from the repeated calls to getBiggestVertex, you visit the nodes in the same order as they appear in the list.

printing the turns of a recursive maze solution in Java

So I've been working on the following problem:
I buried my sapphire then started walking. I always walked in a
straight line following a compass direction (N, S, E, W). When I
stopped, I made a 90 degree turn and continued walking. I might have
crossed my path, but I don’t remember. Below are the number of meters
I travelled in each direction. I’m now lost and must abandon this
record while I search for a way out. I’m placing this note under a
rock at my final location. Perhaps some lucky adventurer will decode
my note and retrace my steps to earn the treasure. Unfortunately,
there is no record of where in the ruins the note was found. Instead,
you must write a program to find the treasure. Input The first
line contains two integers X Y, representing the number of rows and
columns in the ruins. Maximum of 20 rows and 50 columns. The next X
lines show a grid map of the space. A period “.” is an empty square. A
hash “#” is a large boulder, marking a square that cannot be entered.
The next line has an integer N, the count of the straight paths
walked. Maximum of 20 paths. The last line contains N integers
separated by spaces, showing the successive path-lengths.. 5 10
####
........#
.#...##.#
...#....#
#### 8 2 4 2 2 2 5 2 1 Output Your program must print the same map, with the location of both the Sapphire (S) and the final
location of the message (F) marked. Also, label every turning point
with successive lowercase letters (if the same point is used more
than once, print the letter for the later turn.) There is only one
route which follows the path-lengths in the list.
####
b.e.a..f#
.#...##.#
c.d#S.Fg#
#
and I have made a recursive method that checks every direction starting from every open position of the maze until it finds the solution, however the output of the problem needs to be the mazes with the turns.
The problem is, when I use a recursive solution and edit the actual char[][] map, it never knows which path will lead to the actual finish, so it will create output like this:
d...d
.....
cbabc
d...d
but instead I would like it to show only one path, like this:
....d
.....
..abc
.....
Here is my incomplete solution:
import java.util.Scanner;
public class SapphireSearch {
private static int rs; // Row Size
private static int cs; // Column Size
private static int sr; // Save row (saves solution row)
private static int sc; // Save col (saves solution col)
private static Direction sd; // Save direction (saves solution dir)
private static char[][] map; // the maze to traverse
private static int n; // number of turns
private static int[] go; // length of the turns
public static void main(String[] args) {
getInput();
for (int r = 0; r < rs; r++)
for (int c = 0; c < cs; c++)
for (Direction d : Direction.values())
solve(sr = r, sc = c, sd = d, 0, false);
}
public static void solve(int r, int c, Direction d, int start,
boolean printing) {
if (isSolid(r, c))
return;
if (printing) {
if (start == 0)
map[r][c] = 'S';
else
map[r][c] = (char) (start - 1 + 'a');
if (start == n) {
map[r][c] = 'F';
return;
}
}
if (start == n - 1 && !printing) {
solve(sr, sc, sd, 0, true);
printArray(map);
System.exit(0);
}
int count = 0;
while (start < go.length && count < go[start]) {
count++;
r += d.dr;
c += d.dc;
if (isSolid(r, c))
return;
}
for (Direction t : d.turn())
solve(r, c, t, start + 1, printing);
}
public static boolean isSolid(int r, int c) {
return map[r][c] == '#';
}
public static void printArray(char[][] o) {
for (int r = 0; r < o.length; r++) {
for (int c = 0; c < o[r].length; c++)
System.out.print(o[r][c]);
System.out.println();
}
}
private static void getInput() {
Scanner s = new Scanner(System.in);
rs = s.nextInt();
cs = s.nextInt();
s.nextLine(); // clear buffer
map = new char[rs][cs];
for (int r = 0; r < rs; r++) {
int c = 0;
char[] f = s.nextLine().trim().toCharArray();
for (char t : f)
map[r][c++] = t;
}
n = s.nextInt();
go = new int[n];
for (int i = 0; i < n; i++)
go[i] = s.nextInt();
}
}
enum Direction {
// deltaR, deltaC
up(-1, 0), down(1, 0), left(0, -1), right(0, 1);
public int dr;
public int dc;
private Direction(int dr, int dc) {
this.dr = dr;
this.dc = dc;
}
public Direction[] turn() {
Direction[] out = new Direction[2];
switch (this) {
case up:
case down:
out[0] = left;
out[1] = right;
break;
case left:
case right:
out[0] = up;
out[1] = down;
}
return out;
}
}
The question is: building upon my recursive solve algorithm, what would be the best way to print the solution path (where it doesn't print out every path it tries to take)?
You need to build up your list of turns as you do the recursive search (I'm just listing the direction here for simplicity but you could store an object with co-ordinates as well for example).
If the path is (N,E,N,W,S) and then save that as you exit.
To do that keep the partial list so far and each recursive call COPY the list so far and add to it.
i.e.:
n
ne
nw Fail
nen
nes Fail
nenw
etc.
At the end you can either return the completed solution or if you need to handle multiple solutions have a final results list of lists that you insert the completed one into.
The key step is to copy the list so far so that recursion branches cannot interfere with each other.

Solve n-puzzle in Java

I'm trying to implement a program to solve the n-puzzle problem.
I have written a simple implementation in Java that has a state of the problem characterized by a matrix representing the tiles. I am also able to auto-generate the graph of all the states giving the starting state. On the graph, then, I can do a BFS to find the path to the goal state.
But the problem is that I run out of memory and I cannot even create the whole graph.
I tried with a 2x2 tiles and it works. Also with some 3x3 (it depends on the starting state and how many nodes are in the graph). But in general this way is not suitable.
So I tried generating the nodes at runtime, while searching. It works, but it is slow (sometimes after some minutes it still have not ended and I terminate the program).
Btw: I give as starting state only solvable configurations and I don't create duplicated states.
So, I cannot create the graph. This leads to my main problem: I have to implement the A* algorithm and I need the path cost (i.e. for each node the distance from the starting state), but I think I cannot calculate it at runtime. I need the whole graph, right? Because A* does not follow a BFS exploration of the graph, so I don't know how to estimate the distance for each node. Hence, I don't know how to perform an A* search.
Any suggestion?
EDIT
State:
private int[][] tiles;
private int pathDistance;
private int misplacedTiles;
private State parent;
public State(int[][] tiles) {
this.tiles = tiles;
pathDistance = 0;
misplacedTiles = estimateHammingDistance();
parent = null;
}
public ArrayList<State> findNext() {
ArrayList<State> next = new ArrayList<State>();
int[] coordZero = findCoordinates(0);
int[][] copy;
if(coordZero[1] + 1 < Solver.SIZE) {
copy = copyTiles();
int[] newCoord = {coordZero[0], coordZero[1] + 1};
switchValues(copy, coordZero, newCoord);
State newState = checkNewState(copy);
if(newState != null)
next.add(newState);
}
if(coordZero[1] - 1 >= 0) {
copy = copyTiles();
int[] newCoord = {coordZero[0], coordZero[1] - 1};
switchValues(copy, coordZero, newCoord);
State newState = checkNewState(copy);
if(newState != null)
next.add(newState);
}
if(coordZero[0] + 1 < Solver.SIZE) {
copy = copyTiles();
int[] newCoord = {coordZero[0] + 1, coordZero[1]};
switchValues(copy, coordZero, newCoord);
State newState = checkNewState(copy);
if(newState != null)
next.add(newState);
}
if(coordZero[0] - 1 >= 0) {
copy = copyTiles();
int[] newCoord = {coordZero[0] - 1, coordZero[1]};
switchValues(copy, coordZero, newCoord);
State newState = checkNewState(copy);
if(newState != null)
next.add(newState);
}
return next;
}
private State checkNewState(int[][] tiles) {
State newState = new State(tiles);
for(State s : Solver.states)
if(s.equals(newState))
return null;
return newState;
}
#Override
public boolean equals(Object obj) {
if(this == null || obj == null)
return false;
if (obj.getClass().equals(this.getClass())) {
for(int r = 0; r < tiles.length; r++) {
for(int c = 0; c < tiles[r].length; c++) {
if (((State)obj).getTiles()[r][c] != tiles[r][c])
return false;
}
}
return true;
}
return false;
}
Solver:
public static final HashSet<State> states = new HashSet<State>();
public static void main(String[] args) {
solve(new State(selectStartingBoard()));
}
public static State solve(State initialState) {
TreeSet<State> queue = new TreeSet<State>(new Comparator1());
queue.add(initialState);
states.add(initialState);
while(!queue.isEmpty()) {
State current = queue.pollFirst();
for(State s : current.findNext()) {
if(s.goalCheck()) {
s.setParent(current);
return s;
}
if(!states.contains(s)) {
s.setPathDistance(current.getPathDistance() + 1);
s.setParent(current);
states.add(s);
queue.add(s);
}
}
}
return null;
}
Basically here is what I do:
- Solver's solve has a SortedSet. Elements (States) are sorted according to Comparator1, which calculates f(n) = g(n) + h(n), where g(n) is the path cost and h(n) is a heuristic (the number of misplaced tiles).
- I give the starting configuration and look for all the successors.
- If a successor has not been already visited (i.e. if it is not in the global set States) I add it to the queue and to States, setting the current state as its parent and parent's path + 1 as its path cost.
- Dequeue and repeat.
I think it should work because:
- I keep all the visited states so I'm not looping.
- Also, there won't be any useless edge because I immediately store current node's successors. E.g.: if from A I can go to B and C, and from B I could also go to C, there won't be the edge B->C (since path cost is 1 for each edge and A->B is cheaper than A->B->C).
- Each time I choose to expand the path with the minimum f(n), accordin to A*.
But it does not work. Or at least, after a few minutes it still can't find a solution (and I think is a lot of time in this case).
If I try to create a tree structure before executing A*, I run out of memory building it.
EDIT 2
Here are my heuristic functions:
private int estimateManhattanDistance() {
int counter = 0;
int[] expectedCoord = new int[2];
int[] realCoord = new int[2];
for(int value = 1; value < Solver.SIZE * Solver.SIZE; value++) {
realCoord = findCoordinates(value);
expectedCoord[0] = (value - 1) / Solver.SIZE;
expectedCoord[1] = (value - 1) % Solver.SIZE;
counter += Math.abs(expectedCoord[0] - realCoord[0]) + Math.abs(expectedCoord[1] - realCoord[1]);
}
return counter;
}
private int estimateMisplacedTiles() {
int counter = 0;
int expectedTileValue = 1;
for(int i = 0; i < Solver.SIZE; i++)
for(int j = 0; j < Solver.SIZE; j++) {
if(tiles[i][j] != expectedTileValue)
if(expectedTileValue != Solver.ZERO)
counter++;
expectedTileValue++;
}
return counter;
}
If I use a simple greedy algorithm they both work (using Manhattan distance is really quick (around 500 iterations to find a solution), while with number of misplaced tiles it takes around 10k iterations). If I use A* (evaluating also the path cost) it's really slow.
Comparators are like that:
public int compare(State o1, State o2) {
if(o1.getPathDistance() + o1.getManhattanDistance() >= o2.getPathDistance() + o2.getManhattanDistance())
return 1;
else
return -1;
}
EDIT 3
There was a little error. I fixed it and now A* works. Or at least, for the 3x3 if finds the optimal solution with only 700 iterations. For the 4x4 it's still too slow. I'll try with IDA*, but one question: how long could it take with A* to find the solution? Minutes? Hours? I left it for 10 minutes and it didn't end.
There is no need to generate all state space nodes for solving a problem using BFS, A* or any tree search, you just add states you can explore from current state to the fringe and that's why there is a successor function.
If BFS consumes much memory it is normal. But I don't know exactly fro what n it would make problem. Use DFS instead.
For A* you know how many moves you made to come to current state and you can estimate moves need to solve problem, simply by relaxing problem. As an example you can think that any two tiles can replace and then count moves needed to solve the problem. You heuristic just needs to be admissible ie. your estimate be less then actual moves needed to solve the problem.
add a path cost to your state class and every time you go from a parent state P to another state like C do this : c.cost = P.cost + 1 this will compute the path cost for every node automatically
this is also a very good and simple implementation in C# for 8-puzzle solver with A* take a look at it you will learn many things :
http://geekbrothers.org/index.php/categories/computer/12-solve-8-puzzle-with-a

I need an algorithm to get the chromatic number of a graph

Given the adjacency matrix of a graph, I need to obtain the chromatic number (minimum number of colours needed to paint every node of a graph so that adjacent nodes get different colours).
Preferably it should be a java algorithm, and I don't care about performance.
Thanks.
Edit:
recently introduced a fix so the answer is more accurately. now it will recheck his position with his previous positions.
Now a new question comes up. Which will be better to raise his 'number-color'? the node in which i am standing, or the node i am visiting (asking if i am adjacent to it)?
public class Modelacion {
public static void main(String args[]) throws IOException{
// given the matrix ... which i have hidden the initialization here
int[][] matriz = new int[40][40];
int color[] = new int[40];
for (int i = 0 ; i<40;i++)
color[i]=1;
Cromatico c = new Cromatico(matriz, color);
}
}
import java.io.IOException;
public class Cromatico {
Cromatico(int[][]matriz, int[] color, int fila) throws IOException{
for (int i = 0; i<fila;i++){
for (int j = 0 ; j<fila;j++){
if (matriz[i][j] == 1 && color[i] == color [j]){
if (j<i)
color [i] ++;
else
color [j] ++;
}
}
}
int numeroCromatico = 1;
for (int k = 0; k<fila;k++){
System.out.print(".");
numeroCromatico = Math.max(numeroCromatico, color[k]);
}
System.out.println();
System.out.println("el numero cromatico del grafo es: " + numeroCromatico);
}
}
Finding the chromatic number of a graph is NP-Complete (see Graph Coloring). It is NP-Complete even to determine if a given graph is 3-colorable (and also to find a coloring).
The wiki page linked to in the previous paragraph has some algorithms descriptions which you can probably use.
btw, since it is NP-Complete and you don't really care about performance, why don't you try using brute force?
Guess a chromatic number k, try all possibilities of vertex colouring (max k^n possibilities), if it is not colorable, new guess for chromatic number = min{n,2k}. If it is k-colorable, new guess for chromatic number = max{k/2,1}. Repeat, following the pattern used by binary search and find the optimal k.
Good luck!
And to answer your edit.
Neither option of incrementing the color will work. Also, your algorithm is O(n^2). That itself is enough to tell it is highly likely that your algorithm is wrong, even without looking for counterexamples. This problem is NP-Complete!
Super slow, but it should work:
int chromaticNumber(Graph g) {
for (int ncolors = 1; true; ncolors++) {
if (canColor(g, ncolors)) return ncolors;
}
}
boolean canColor(Graph g, int ncolors) {
return canColorRemaining(g, ncolors, 0));
}
// recursive routine - the first colors_so_far nodes have been colored,
// check if there is a coloring for the rest.
boolean canColorRemaining(Graph g, int ncolors, int colors_so_far) {
if (colors_so_far == g.nodes()) return true;
for (int c = 0; c < ncolors; c++) {
boolean ok = true;
for (int v : g.adjacent(colors_so_far)) {
if (v < colors_so_far && g.getColor(v) == c) ok = false;
}
if (ok) {
g.setColor(colors_so_far, c);
if (canColorRemaining(g, ncolors, colors_so_far + 1)) return true;
}
}
return false;
}

Categories

Resources