In this program, I am given an input text file that gives information about a weighted, directed graph
G = (V, E, w)
The first line of the text file in input stores V (the number of vertices) and E (the number of edges).
The following lines store data about edges (u, v) in order u, v, weight.
I'm trying to implement a code that considers this input and determines whether G contains a negative-weight cycle.
So far, I've tried to use the Bellman Ford algorithm to try to get this to work: I started by initializing a dist[] array that initializes distances from the source to all other vertices as some really high number (making sure src to src is 0).
Next, I relax all edges |V| - 1 times.
Finally, I check for negative-weight cycles by iterating through the array of edges again, checking to see if we get a shorter path.
However, when I try to do that second step of relaxing the edges, I keep getting an index out of bounds error.
NOTE: To examine the code below, just scroll down to the method isNegativeCycle(). I just included some of the other stuff in case anyone needs background information.
public class P1 {
//instance variables
static int V; //number of vertices
static int E; //number of edges
//vertex class
public class Vertex {
int ID; //the name of the vertex
}
//edge class
public class Edge {
Vertex source; //the source vertex - its a directed graph
Vertex dest; //the destination vertex
int weight; //the weight of the edge
}
//graph class where all the magic happens
public class Graph {
//Each graph has an array of edges
Edge edgearray[];
//constructor
public Graph(int n, int m) {
V = n;
E = m;
edgearray = new Edge[E];
for (int i = 0; i < E; i++) {
edgearray[i] = new Edge();
}
}
//THIS IS THE IMPORTANT METHOD
public String isNegativeCycle(Graph G, int src) {
int dist[] = new int[V];
Arrays.fill(dist, Integer.MAX_VALUE);
dist[src] = 0; //cos the distance from A to A is 0
//Relax all edges
for (int i = 1; i <= V-1; i++) {
for (int j = 0; j < E; j++) {
int u = G.edgearray[j].source.ID;
int v = G.edgearray[j].dest.ID;
int weight = G.edgearray[j].weight;
//THIS IS WHERE I GET THE INDEX OUT OF BOUNDS ERROR
if (dist[u]!= Integer.MAX_VALUE && (dist[u]+weight) < dist[v]) {
dist[v] = dist[u]+weight;
}
}
//check for a negative cycle
for (int a = 0; a < E; a++) {
int u = G.edgearray[a].source.ID;
int v = G.edgearray[a].dest.ID;
double weight = G.edgearray[a].weight;
if (dist[u] != Integer.MAX_VALUE && dist[u]+weight < dist[v]) {
return "YES";
}
}
return "NO";
}
}//end of graph class
//main method
public static void main(String[] args) {
P1 instance = new P1();
int n;
int m;
int counter = 0;
boolean fl = true;
String infileName = args[0];
Graph G = instance.new Graph(V, E);
File infile = new File(infileName);
Scanner fileReader = null;
try {
fileReader = new Scanner(infile);
while (fileReader.hasNextLine()) {
//if we're reading the first line
if (fl == true) {
String[] temp = fileReader.nextLine().split(" ");
n = Integer.parseInt(temp[0]);
V = n;
m = Integer.parseInt(temp[1]);
E = m;
G = instance.new Graph(V, E);
fl = false;
}
//if we're reading any line other than the first line
else {
String[] temp = fileReader.nextLine().split(" ");
//G.addEdge(temp[0], temp[1], Double.parseDouble(temp[2]));
Vertex newsrc = instance.new Vertex();
Vertex newdest = instance.new Vertex();
newsrc.ID = Integer.parseInt(temp[0]);
newdest.ID = Integer.parseInt(temp[1]);
Edge newEdge = instance.new Edge();
newEdge.source = newsrc;
newEdge.dest = newdest;
newEdge.weight = Integer.parseInt(temp[2]);
G.edgearray[counter] = newEdge;
counter++;
}
}
}
catch (FileNotFoundException e) {
System.out.println("File not found.");
}
System.out.println(G.isNegativeCycle(G, 0));
}
}
My current input file doesn't really matter at this point, but after this code runs, I expect the output to be "YES." Thank you!
I should've included my input file. In my input file, you would see that the vertex names start at 1. Thus, when calling isNegativeCycle, I shoudl've sent in a 1 instead of a 0. In addition, I make the dist[] array one size bigger.
Related
I'm having trouble implementing a method to create an array of distances using BFS from a chosen starting vertex, it currently seems to work in some cases, but fails in larger graphs. The idea is each index in the array represents the corresponding vertex in a graph.
here is the relevant code
public int[] getDistances(Graph g, int startVertex) {
boolean[] visited = new boolean[g.getNumberOfVertices()];
int[] distance = new int[g.getNumberOfVertices()];
for (int i = 0; i < distance.length; i++)
{
distance[i] = -1;
}
ArrayList<Integer> q = new ArrayList<Integer>();
q.add(startVertex);
int dist_int = 0;
while (!q.isEmpty())
{
int current = q.get(0);
q.remove(0);
dist_int++;
visited[startVertex] = true;
for (int j = 0; j < g.getEdgeMatrix()[current].length; j++)
{
if (startVertex == j)
distance[j] = 0;
if (g.getEdgeMatrix()[current][j] == 1 && !visited[j])
{
q.add(j);
distance[j] = dist_int;
visited[j] = true;
}
}
}
return distance;
}
the idea is it iterates through an adjacency matrix, determining each unvisited child, each time a child is found the current dist_int is assigned to the corresponding index in the distance array. With the distance increasing each time all of the children of the current node have been assigned, then the current moves to the first child and repeats.
Instead of using dist_int to hold the distance values just call
distance[j] = distance[current] + 1;
Given a tree, assign weights to each edge in order to minimize the weight of every path (u, v) in the tree. To clarify, we are minimizing the maximum weight on every path in the tree
Can this question be solved with some sort of data structure or algorithm? How do you determine which weights to place on each edge in the tree? The input is a number N, and you have to place weights in between the values of [0, N-2] (inclusive) on each edge of the tree.
Let me clarify the question. Let's say you have an edge (1, 2) and you place weight 3 on that edge. The actual definition of "weight" in the context of the question is the minimum-most value from [0, N-2] that IS NOT present on the path from (u, v). Even though the weight on the specific edge is three, the actual weight in the context of the question is zero. Also, the root of the tree in this question is 1.
My original approach for this question was to add the values from [0, N-2] (the edge values we can assign to each edge) to a stack, then traverse the tree using DFS and pop a value from the stack (the maximum-most edge value) and assign it to the edge. This, however, does not minimize the cost over all paths. Keep in mind, the cost is the minimum-most value not present on the path from (u, v). We are trying to place the costs to minimize the costs on every possible path.
My code:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Stack;
import java.util.Iterator;
import java.util.ArrayList;
public class Mex {
public static void main (String [] args) throws IOException {
BufferedReader b1 = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(b1.readLine());
LinkedList<Integer>[] adj = new LinkedList[n+1];
ArrayList<Integer> v = new ArrayList<Integer>(n+1);
for(int i = 1; i<=n; i++) {
adj[i] = new LinkedList<Integer>();
}
for(int i = 0; i<n-1; i++) {
String [] edge = (b1.readLine()).split(" ");
adj[Integer.parseInt(edge[0])].add(Integer.parseInt(edge[1]));
adj[Integer.parseInt(edge[1])].add(Integer.parseInt(edge[0]));
v.add(Integer.parseInt(edge[0]));
v.add(Integer.parseInt(edge[1]));
}
dfs(adj, 1, n, v);
}
static void dfs(LinkedList<Integer> adj[], int u, int n, ArrayList<Integer> order) {
Stack<Integer> values = new Stack<>();
int [][] weight = new int[n+1][n+1];
for(int i = 0; i<n-1; i++) {
values.push(i);
}
boolean [] visited = new boolean[n+1];
int [] parent = new int[n+1];
for (int i = 1; i < n+1; i++)
visited[i] = false;
Stack<Integer> stack = new Stack<>();
stack.push(u);
while(stack.empty() == false) {
u = stack.peek();
stack.pop();
if(visited[u] == false) {
visited[u] = true;
if(u!= 1) {
if(adj[u].size()==1) {
if(values.contains(0)) {
weight[parent[u]][u] = 0;
values.remove(0);
}
else {
int w = values.pop();
weight[parent[u]][u] = w;
}
}
else {
int w = values.pop();
weight[parent[u]][u] = w;
}
}
}
Iterator<Integer> itr = adj[u].iterator();
while (itr.hasNext()) {
int v = itr.next();
if(parent[v]==0 && v!=1) {
parent[v] = u;
}
if(!visited[v])
stack.push(v);
}
}
for(int i = 0; i<order.size()-1; i+=2) {
if(parent[order.get(i)]==order.get(i+1)) {
System.out.println(weight[order.get(i+1)][order.get(i)]);
}
else {
System.out.println(weight[order.get(i)][order.get(i+1)]);
}
}
}
}
There's no special algorithm or data structure that you need to solve this problem. There is just one key observation you need to make:
If every vertex in your graph has degree 2 or less, then no matter how you place the vertices, there's always a path that touches every edge. Therefore, it doesn't matter how you place the labels.
If there's at least one vertex in your graph with degree 3 or more, then we can place the labels 0, 1, and 2 on edges incident to a common vertex. Now, the maximum minimum excludant is 2 since we can take a path from 0 to 1. It's pretty clear that you can't do better than this since you can always start at 0 and go to 1 to get a minimum excludant of 2. Therefore, you can make the edges 0, 1, and 2 incident to the same vertex. The other labels don't matter.
I have implemented an program that can calculate shortest path's for any graph either by using Floyd's/Dijkstra's algorithm based on user input.
Both algorithm's work fine for directed graph.
The output is supposed to display
1)The actual path to be taken from the start vertex
2)The shortest distance to be travelled
But when it come's to undirected graph I run into problems.
My graph is not represented by an adjacency matrix but with an Graph & Edge classes as shown below
class Graph
{
private final int noOfVertices;
private final ArrayList<Edge> edges = new ArrayList<Edge>();
private boolean undirected = false;
Graph(int vertexCount)
{
noOfVertices = vertexCount;
edges.ensureCapacity(2 * (vertexCount - 1));
}
public int getWeight(int src,int dst)
{
int weight=90000;
for(Edge edge:edges)
{
if(edge.src==src && edge.dst==dst)
{
weight=edge.weight;
break;
}
}
return weight;
}
public int getEdgeCount(){return edges.size();}
public int getVertexCount(){return noOfVertices;}
public static class Edge
{
public int src;
public int dst;
public int weight;
Edge(int v1, int v2, int w)
{
src = v1;
dst = v2;
weight = w;
}
}
}
To implement undirected graph this is the code used below
void newEdge(int src,int dst,int weight)
{
edges.add(new Edge(src,dst,weight));
if(undirected){ edges.add(new Edge(dst,src,weight));}
}
Now Dijkstra's algorithm work's fine on this setup but when I use Floyd's algorithm I start to get incorrect path's but correct distance's
This is my Floyd's algorithm
public static Integer[] Floyd(Graph graph, int startVertex, int endVertex)
{
ArrayList<Integer> pathInfo = new ArrayList<Integer>();
int dist[][] = new int[graph.getVertexCount()][graph.getVertexCount()];
int path[][] = new int[graph.getVertexCount()][graph.getVertexCount()];
int V = graph.getVertexCount();
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (i == j)
{
dist[i][j] = 0;
}
else
{
dist[i][j] = graph.getWeight(i, j);
}/*Initialize with edge weight's between vertices i,j.If edge does not exist graph.getWeight() return's 90000 i.e simply an value somewhat close to infinite because when I use Integer.MAX_VALUE I get negative distance's when doing dist[i][k]+dist[k][j] so i avoid it*/
path[i][j] = j;
}
}
/*actual Floyd's algorithm*/
for (int k = 0; k < V; k++)
{
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = k; /*if path exist's record the intermediate vertex*/
}
}
}
}
int currentVertex=endVertex; /*Start from last vertex*/
int nextVertex=path[startVertex][endVertex];/*Find path*/
pathInfo.add(currentVertex);/*Add Current Vertex*/
while(currentVertex!=nextVertex)/*Backtrack until the vertex we are currently at and the next vertex we need to go to from there are the same which mean's we have reached our target*/
{
currentVertex=nextVertex;
pathInfo.add(0,currentVertex);
nextVertex=path[startVertex][nextVertex];
}
pathInfo.add(0,startVertex);/*Finally add the vertex we ended at*/
pathInfo.add(dist[startVertex][endVertex]);/*Come's out correct in both cases*/
return pathInfo.toArray(new Integer[]{});/*Convert info to array*/
}
So here is my undirected graph given below.
The doted lines represent's an edge that goes in both direction's.
0--1--2--3
Each edge has an weight of 2
Now when I call Floyd's algorithm with start vertex=0 and end vertex=3
I get The correct output path.
0,1,2,3
But when I again call Floyd's algorithm with start Vertex=3 and end Vertex=0
The output path is
3,2,0
Vertex 1 is missing.
But with Dijkstra's algorithm I get the correct result's in both cases
Here is the path matrix calculated above.
0 1 1 2
0 1 2 2
1 1 2 3
2 2 2 3
The distance come's out correct that is 6 in both cases but the path is wrong when I reverse the vertex order only for Floyd's algorithm.
Most of the video ideas were incorporated from this link
https://www.bing.com/videos/search?q=floyd%27s+algorithm&&view=detail&mid=E17F409B3AB0B2307233E17F409B3AB0B2307233&&FORM=VRDGAR
Any idea's on where I went wrong?
Really stumped on this one, don't know where to begin. I thought about making a separate method which calculates the paths between two different vertices, but I don't know how I would implement that.
I thought that finding the minimum degree of the graph and then adding one would give me the girth, but that is assuming there is a cycle in the graph. So I would need the program to scan through the adjacency matrix, somehow uses the true values to find out if there is a cycle or not and then calculate the distance of that cycle.
Looking for a step in the right direction.
Also I'm looking to not use the ArrayList approach, hence why I'm stumped
This is what I have so far:
import java.util.Scanner;
import java.util.*;
public class Graph {
// Setup privately modified variables which will define the graph
// These two parameters are storage variables for edges and vertices
//These variables were changed from Vertex and Edge to numVertices and numEdges.
private int numVertices;
private int numEdges;
// This will be the adjacency matrix to represent our graph, this will
// represent edges.
// adj_Matrix_Edges was previously static meaning it did not have access to multiple graphs, onyl one graph.
private boolean[][] adj_Matrix_Edges;
// first step will be to setup the graph, using this constructor
public Graph(int vertices) {
numVertices = vertices;
if (numVertices < 0) {
throw new RuntimeException(
"Number of vertices cannot be a nonnegative value");
}
System.out.println("There are now " + numVertices
+ " vertices in the graph.");
// A graph is created based on the specifications, N X N or (n^2)
// graph.
adj_Matrix_Edges = new boolean[vertices][vertices];
}
// This method validates whether or not two vertices are adjacent, returns
// true if adjacent false otherwise.
public boolean adjacent(int i, int j) {
if (adj_Matrix_Edges[i][j] == true) {
return true;
} else {
return false;
}
}
// I needed a review of this class so I had to read about ArrayList class, but it allows
// you to iterate the columns in the adjacency matrix.
// It also allows you to print out integers values instead of booleans
// The for loop, loops over a column you would select, and then the if
// statement checks for an incident in that column.
public List<Integer> neighbors(int vertex) {
List<Integer> neighbors = new ArrayList<Integer>();
for (int i = 0; i < adj_Matrix_Edges.length; i++) {
// The if statement here does not need an equality sign since
// booleans are in the 2-d matrix.
if (adj_Matrix_Edges[vertex][i]) {
// adds that vertex i to the list
neighbors.add(i);
}
}
System.out.println("The neighbors of vertex " + vertex + " are " + neighbors);
return neighbors;
}
//This method will count the number of neighbors for a specific vertex.
public double averageDegree(){
//create a variable for the count, and initialize the counter to 0.
double neighborCount = 0;
for (int i = 0; i < adj_Matrix_Edges.length; i++){
for (int j = 0; j < adj_Matrix_Edges[i].length; j++){
//this if statement scans the specific vertex for true statements in the boolean array
if (adj_Matrix_Edges[i][j]){
// this logical expression adds up the count of the true statements, in graph theory this is adding up the
// degree of that specific vertex.
neighborCount++;
}
}
}
neighborCount= neighborCount / numVertices;
System.out.println("The average degree of the graph is " + neighborCount);
return neighborCount;
}
public boolean[][] addVertex() {
// add an extra vertex to the graph.
numVertices++;
// secondly we have to copy over the contents of the old array into a new array.
// Initialize a new array
boolean[][] new_adj_Matrix_Edges = adj_Matrix_Edges;
// setup a for loop which sets up new values for
for (int i = 0; i < adj_Matrix_Edges.length; i++){
for (int j = 0; j < adj_Matrix_Edges.length; j++){
adj_Matrix_Edges[i][j] = new_adj_Matrix_Edges[i + 1][j + 1];
}
}
return new_adj_Matrix_Edges;
}
public boolean[][] removeVertex(int vertex){
// set a local variable.
int vertex_Selected = vertex;
// create a new 2-d array where you can copy the old one over.
boolean[][] new_adj_Matrix_Edges = adj_Matrix_Edges;
//create a for loop setup to copy over all data from old array to the new array.
for (int g = 0; g < adj_Matrix_Edges.length; g++){
for (int h = 0; h < adj_Matrix_Edges[g].length; h++){
adj_Matrix_Edges[g][h] = new_adj_Matrix_Edges[g][h];
}
}
// now that a new array has been created, and all information is copied over we can then set
// all values of the selected vertex to false.
for (int i = 0; i < new_adj_Matrix_Edges.length; i++){
for (int j = 0; j < new_adj_Matrix_Edges[i].length; j++){
if (new_adj_Matrix_Edges[vertex_Selected][j] == true){
new_adj_Matrix_Edges[vertex_Selected][j] = false;
}
if (new_adj_Matrix_Edges[i][vertex_Selected] == true){
new_adj_Matrix_Edges[i][vertex_Selected] = false;
}
}
}
return new_adj_Matrix_Edges;
}
public void addEdge(int vertex_add_1, int vertex_add_2) {
if (adj_Matrix_Edges[vertex_add_1][vertex_add_2] == false) {
adj_Matrix_Edges[vertex_add_1][vertex_add_2] = true;
adj_Matrix_Edges[vertex_add_2][vertex_add_1] = true;
} else {
System.out.println("There is already an edge between vertex "
+ vertex_add_1 + " and vertex " + vertex_add_2 + ".");
}
}
// This method removes an edge if the two int values in the 2-d boolean
// array are true, converts to false, otherwise it stays false if no edge
// present
public void removeEdge(int vertex_remove_1, int vertex_remove_2) {
if (adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] == true) {
adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] = false;
adj_Matrix_Edges[vertex_remove_1][vertex_remove_2] = false;
} else {
System.out.println("There is no edge between vertex "
+ vertex_remove_1 + " and vertex " + vertex_remove_2);
}
}
// setup a method which finds the shortest cycle in the graph.
// We want to set the method to return an int value, because the girth of the graph will represent an integer value
// which cannot be a negative value.
// if we find the diameter of a graph then the shortest cycle will be the girth, which will be the
// 2diam(G) + 1.
public int girth(){
// Set the
}
public int pathVertices(int vertex_1, int vertex_2){
if (vertex_1 != vertex_2){
}
}
public static void main(String[] args) {
// Make an arbritary graph with 5 vertices.
Graph graph = new Graph(10);
graph.addEdge(1, 2);
graph.removeEdge(0, 1);
graph.adjacent(1, 2);
graph.adjacent(2, 1);
graph.neighbors(1);
graph.neighbors(4);
graph.addVertex();
graph.removeVertex(0);
graph.averageDegree();
// for (int i = 0; i < adj_Matrix_Edges.length; i++) {
// for (int j = 0; j < adj_Matrix_Edges[i].length; j++) {
// System.out.println(adj_Matrix_Edges[i][j] + " ");
// }
// System.out.println("-----");
// }
}
}
I'm having a headache implementing this (awful) pseudo-java code (I wonder: why the hell people do that?) for the b&b knapsack problem. This is my implementation so far, which outputs a maximum of 80 (when it should print 90, for the items on the textbook sample). I created a Comparator (on a LinkedList) to sort the elements by Pi/Wi before passing them to the algorithm, but on this input is already presorted. I'm debugging right now (and updating the posted code), cause I guess it's an array indexing problem... or is there a mistake on the bounding function?
input:
4 16 //# items maxWeight
40 2 // profit weight
30 5
50 10
10 5
class Node
{
int level;
int profit;
int weight;
double bound;
}
public class BranchAndBound {
static int branchAndBound (LinkedList<Item> items, int W) {
int n = items.size();
int [] p= new int[n];
int [] w= new int[n];
for (int i=0; i<n;i++){
p [i]= (int)items.get(i).value;
w [i]= (int)items.get(i).weight;
}
Node u = new Node();
Node v = new Node(); // tree root
int maxProfit=0;
LinkedList <Node> Q = new LinkedList<Node>();
v.level=-1;
v.profit=0;
v.weight=0; // v initialized to -1, dummy root
Q.offer(v); // place the dummy at the root
while(!Q.isEmpty()){
v = Q.poll();
if (v.level==-1){
u.level=0;
}
else if(v.level != (n - 1))
{
u.level = v.level+1; // set u to be a child of v
}
u = new Node();
u.weight = v.weight + w[u.level];// set u to the child
u.profit = v.profit + p[u.level]; // that includes the
//next item
double bound = bound(u, W, n, w, p);
u.bound=bound;
if(u.weight<=W && u.profit>maxProfit){
maxProfit = u.profit;
}
if(bound>maxProfit){
Q.add(u);
}
u = new Node();
u.weight = v.weight; // set u to the child that
u.profit = v.profit;// does NOT include the next item
bound = bound(u, W, n, w, p);
u.bound = bound;
if (bound>maxProfit){
Q.add(u);
}
}
return maxProfit;
}
public static float bound(Node u, int W, int n, int [] w, int [] p){
int j=0; int k=0;
int totWeight=0;
float result=0;
if(u.weight>=W)
return 0;
else {
result = u.profit;
j= u.level +1;
totWeight = u.weight;
while ((j < n) && (totWeight + w[j]<=W)){
totWeight = totWeight + w[j]; // grab as many items as possible
result = result + p[j];
j++;
}
k=j; // use k for consistency with formula in text
if (k<n)
result = result + (W-totWeight) * p[k]/w[k];// grab fraction of kth item
return result;
}
}
}
I have only tested it with the given example, but it looks like that wherever the pseudocode says
enqueue(Q, u)
you should add a copy of u to the linked list, rather than passing a reference to u and continue manipulating it.
In other words, define a copy constructor for the class Node and do
Q.offer(new Node(u));
instead of
Q.offer(u);
In fact, the code you give above only allocates two instances of the class Node per call to branchAndBound(..)