School Commit Init
This commit is contained in:
@@ -0,0 +1,349 @@
|
||||
package DirectedGraphJava;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DirectedGraph implements IDirectedGraph {
|
||||
private HashSet<Integer> _vertices = new HashSet<Integer>();
|
||||
private HashMap<Integer, HashSet<Integer>> _inbounds = new HashMap<Integer, HashSet<Integer>>();
|
||||
private HashMap<Integer, HashSet<Integer>> _outbounds = new HashMap<Integer, HashSet<Integer>>();
|
||||
private HashMap<Pair<Integer,Integer>,Integer> _edges = new HashMap<Pair<Integer,Integer>,Integer>();
|
||||
|
||||
public DirectedGraph() {
|
||||
//nothing to do
|
||||
}
|
||||
|
||||
public DirectedGraph reindex(){
|
||||
HashMap<Integer,Integer> oldToNew = new HashMap<Integer,Integer>();
|
||||
int i = 0;
|
||||
for (Integer vertex : _vertices) {
|
||||
oldToNew.put(vertex,i);
|
||||
i++;
|
||||
}
|
||||
DirectedGraph newGraph = new DirectedGraph();
|
||||
for (Integer vertex : _vertices) {
|
||||
newGraph.addVertex(oldToNew.get(vertex));
|
||||
}
|
||||
for (Pair<Integer,Integer> edge : _edges.keySet()) {
|
||||
newGraph.addEdge(oldToNew.get(edge.first),oldToNew.get(edge.second),_edges.get(edge));
|
||||
}
|
||||
return newGraph;
|
||||
}
|
||||
|
||||
public Integer numVertices() {
|
||||
return _vertices.size();
|
||||
}
|
||||
|
||||
public Integer numEdges() {
|
||||
return _edges.size();
|
||||
}
|
||||
|
||||
public Iterator<Integer> vertices() {
|
||||
return _vertices.iterator();
|
||||
}
|
||||
|
||||
public Iterator<Pair<Pair<Integer,Integer>,Integer>> edges() {
|
||||
HashSet<Pair<Pair<Integer,Integer>,Integer>> keyValues = new HashSet<Pair<Pair<Integer,Integer>,Integer>>();
|
||||
for (Pair<Integer,Integer> key : this._edges.keySet()) {
|
||||
Pair<Pair<Integer,Integer>,Integer> keyValuePair = new Pair<Pair<Integer,Integer>,Integer>(key,this._edges.get(key));
|
||||
keyValues.add(keyValuePair);
|
||||
}
|
||||
return keyValues.iterator();
|
||||
}
|
||||
|
||||
public boolean isEdge(Integer v1, Integer v2) {
|
||||
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
return _edges.containsKey(new Pair<Integer,Integer>(v1,v2));
|
||||
}
|
||||
|
||||
public int inDegree(Integer v) {
|
||||
if(!_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
return _inbounds.get(v).size();
|
||||
}
|
||||
|
||||
public int outDegree(Integer v) {
|
||||
if(!_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
return _outbounds.get(v).size();
|
||||
}
|
||||
|
||||
public Iterator<Integer> inbounds(Integer v) {
|
||||
if(!_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
return _inbounds.get(v).iterator();
|
||||
}
|
||||
|
||||
public Iterator<Integer> outbounds(Integer v) {
|
||||
if(!_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
return _outbounds.get(v).iterator();
|
||||
}
|
||||
|
||||
public Integer weight(Integer v1, Integer v2) {
|
||||
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
|
||||
throw new IllegalArgumentException("Edge does not exist");
|
||||
}
|
||||
return _edges.get(new Pair<Integer,Integer>(v1,v2));
|
||||
}
|
||||
|
||||
public void weight(Integer v1, Integer v2, Integer w) {
|
||||
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
|
||||
throw new IllegalArgumentException("Edge does not exist");
|
||||
}
|
||||
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
|
||||
}
|
||||
|
||||
public void addVertex(Integer v) {
|
||||
if(_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex already exists");
|
||||
}
|
||||
_vertices.add(v);
|
||||
_inbounds.put(v,new HashSet<Integer>());
|
||||
_outbounds.put(v,new HashSet<Integer>());
|
||||
}
|
||||
|
||||
public void removeVertex(Integer v) {
|
||||
if(!_vertices.contains(v)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
_vertices.remove(v);
|
||||
for (Integer vertex : _inbounds.get(v)) {
|
||||
_outbounds.get(vertex).remove(v);
|
||||
_edges.remove(new Pair<Integer,Integer>(vertex,v));
|
||||
}
|
||||
for (Integer vertex : _outbounds.get(v)) {
|
||||
_inbounds.get(vertex).remove(v);
|
||||
_edges.remove(new Pair<Integer,Integer>(v,vertex));
|
||||
}
|
||||
_inbounds.remove(v);
|
||||
_outbounds.remove(v);
|
||||
}
|
||||
|
||||
public void addEdge(Integer v1, Integer v2, Integer w) {
|
||||
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
if(_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
|
||||
throw new IllegalArgumentException("Edge already exists");
|
||||
}
|
||||
_edges.put(new Pair<Integer,Integer>(v1,v2),w);
|
||||
_inbounds.get(v2).add(v1);
|
||||
_outbounds.get(v1).add(v2);
|
||||
}
|
||||
|
||||
public void removeEdge(Integer v1, Integer v2) {
|
||||
if(!_vertices.contains(v1) || !_vertices.contains(v2)) {
|
||||
throw new IllegalArgumentException("Vertex does not exist");
|
||||
}
|
||||
if(!_edges.containsKey(new Pair<Integer,Integer>(v1,v2))) {
|
||||
throw new IllegalArgumentException("Edge does not exist");
|
||||
}
|
||||
_edges.remove(new Pair<Integer,Integer>(v1,v2));
|
||||
_inbounds.get(v2).remove(v1);
|
||||
_outbounds.get(v1).remove(v2);
|
||||
}
|
||||
|
||||
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v){
|
||||
//Initializations
|
||||
Queue<Integer> queue = new LinkedList<Integer>();
|
||||
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
|
||||
Set<Integer> visited = new HashSet<Integer>();
|
||||
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
|
||||
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
|
||||
}
|
||||
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
|
||||
map.put(v,new Pair<Integer,Integer>(null,0));
|
||||
queue.add(v);
|
||||
map.put(v,new Pair<Integer,Integer>(null,0));
|
||||
visited.add(v);
|
||||
//BFS to find the shortest path
|
||||
while(!queue.isEmpty()){
|
||||
Integer current = queue.poll(); //Get the next vertex
|
||||
//For each neighbor of the current vertex
|
||||
for(Integer neighbor : _outbounds.get(current)){
|
||||
//If the neighbor has not been visited, add it to the queue, the visited set, and the map of distances and parents with a distance of 1 more than the current vertex
|
||||
if(!visited.contains(neighbor)){
|
||||
queue.add(neighbor);
|
||||
visited.add(neighbor);
|
||||
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
public HashMap<Integer,Pair<Integer,Integer>> shortestPath(Integer v,Integer u){
|
||||
//Initializations
|
||||
Queue<Integer> queue = new LinkedList<Integer>();
|
||||
HashMap<Integer,Pair<Integer,Integer>> map = new HashMap<Integer,Pair<Integer,Integer>>();
|
||||
Set<Integer> visited = new HashSet<Integer>();
|
||||
for(Iterator<Integer> vertex = this._vertices.iterator();vertex.hasNext();){
|
||||
map.put(vertex.next(),new Pair<Integer,Integer>(null,-1));
|
||||
}
|
||||
//Add the first vertex to the queue, the visited set, and the map of distances and parents with a distance of 0
|
||||
map.put(v,new Pair<Integer,Integer>(null,0));
|
||||
queue.add(v);
|
||||
map.put(v,new Pair<Integer,Integer>(null,0));
|
||||
visited.add(v);
|
||||
//BFS to find the shortest path
|
||||
while(!queue.isEmpty()){
|
||||
Integer current = queue.poll(); //Get the next vertex
|
||||
//For each neighbor of the current vertex
|
||||
for(Integer neighbor : _outbounds.get(current)){
|
||||
//If the neighbor has not been visited yet add it to the queue, visited set, and map.
|
||||
if(!visited.contains(neighbor)){
|
||||
queue.add(neighbor);
|
||||
visited.add(neighbor);
|
||||
//Add the neighbor to the map with the current vertex as its parent and a distance of the current vertex's distance + 1
|
||||
map.put(neighbor,new Pair<Integer,Integer>(current,map.get(current).second+1));
|
||||
//If the neighbor is the destination vertex return the map
|
||||
if(neighbor == u)
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
public ArrayList<Integer> path(Integer v1,Integer v2){
|
||||
//Get the shortest path from v1 to v2
|
||||
HashMap<Integer,Pair<Integer,Integer>> map = shortestPath(v1);
|
||||
ArrayList<Integer> path = new ArrayList<Integer>();
|
||||
//If there is no path return an empty arraylist
|
||||
if(map.get(v2).second == -1)
|
||||
return path;
|
||||
path.add(v2);
|
||||
//Add each vertex in the path to the arraylist starting from the destination vertex
|
||||
while(map.containsKey(v2)){
|
||||
path.add(map.get(v2).first);
|
||||
v2 = map.get(v2).first;
|
||||
}
|
||||
//Remove the first element of the arraylist which is null and reverse the arraylist
|
||||
path.remove(path.size()-1);
|
||||
Collections.reverse(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCost(){
|
||||
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = new HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>>();
|
||||
for(Integer i : _vertices){
|
||||
for(Integer j : _vertices){
|
||||
if(i==j){
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(0,null));
|
||||
}
|
||||
else if(_edges.containsKey(new Pair<Integer,Integer>(i,j))){
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(_edges.get(new Pair<Integer,Integer>(i,j)),i));
|
||||
}
|
||||
else{
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(10000,null));
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Integer k : _vertices){
|
||||
for(Integer i : _vertices){
|
||||
for(Integer j : _vertices){
|
||||
if(cost_prev_map.get(new Pair<Integer,Integer>(i,j)).first > cost_prev_map.get(new Pair<Integer,Integer>(i,k)).first + cost_prev_map.get(new Pair<Integer,Integer>(k,j)).first){
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,j),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(i,k)).first + cost_prev_map.get(new Pair<Integer,Integer>(k,j)).first,cost_prev_map.get(new Pair<Integer,Integer>(k,j)).second));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Check for negative cycles
|
||||
for(Integer i : _vertices){
|
||||
if(cost_prev_map.get(new Pair<Integer,Integer>(i,i)).first < 0){
|
||||
throw new IllegalArgumentException("Graph contains negative cycle");
|
||||
}
|
||||
}
|
||||
|
||||
return cost_prev_map;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> costPath(Integer v1,Integer v2){
|
||||
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = shortestCost();
|
||||
ArrayList<Integer> path = new ArrayList<Integer>();
|
||||
if(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).first == 10000){
|
||||
return path;
|
||||
}
|
||||
path.add(v2);
|
||||
while(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second != null){
|
||||
path.add(cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second);
|
||||
v2 = cost_prev_map.get(new Pair<Integer,Integer>(v1,v2)).second;
|
||||
}
|
||||
Collections.reverse(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
public HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> shortestCostDynamic(Integer v1, Integer v2){
|
||||
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = new HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>>();
|
||||
//Initialize the map with the first vertex having a distance of 0 and all other vertices having a distance of 10000
|
||||
for(Integer i : _vertices){
|
||||
if(i==v1){
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(0,null));
|
||||
}
|
||||
else{
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,0),new Pair<Integer,Integer>(10000,null));
|
||||
}
|
||||
}
|
||||
//For each iteration of k
|
||||
for(Integer k = 1; k < _vertices.size(); k++){
|
||||
for(Integer i : _vertices){
|
||||
for(Integer j : _vertices){
|
||||
//If the vertex is an edge and the cost of the previous vertex is greater than the current vertex's cost
|
||||
if(this.isEdge(j,i) && cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first > cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i)){
|
||||
//Set the cost of the current vertex to the cost of the previous vertex
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(j,k-1)).first + this.weight(j,i),j));
|
||||
}
|
||||
}
|
||||
//If the vertex is not an edge and the cost of the previous vertex is greater than the current vertex's cost
|
||||
if(!cost_prev_map.containsKey(new Pair<Integer,Integer>(i,k))){
|
||||
//Set the cost of the current vertex to the cost of the previous vertex
|
||||
cost_prev_map.put(new Pair<Integer,Integer>(i,k),new Pair<Integer,Integer>(cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).first,cost_prev_map.get(new Pair<Integer,Integer>(i,k-1)).second));
|
||||
}
|
||||
}
|
||||
}
|
||||
//Check for negative cycles
|
||||
if(cost_prev_map.get(new Pair<Integer,Integer>(v1,v1)).first < 0){
|
||||
throw new IllegalArgumentException("Graph contains negative cycle");
|
||||
}
|
||||
return cost_prev_map;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> costPathDynamic(Integer v1,Integer v2){
|
||||
HashMap<Pair<Integer,Integer>,Pair<Integer,Integer>> cost_prev_map = shortestCostDynamic(v1,v2);
|
||||
ArrayList<Integer> path = new ArrayList<Integer>();
|
||||
//If the cost of the last vertex is 10000(infinity), then there is no path
|
||||
if(cost_prev_map.get(new Pair<Integer,Integer>(v2,_vertices.size()-1)).first == 10000){
|
||||
return path;
|
||||
}
|
||||
//Add the last vertex to the path
|
||||
path.add(v2);
|
||||
Integer k = _vertices.size()-1;
|
||||
//While the previous vertex is not null (the first vertex), add the previous vertex to the path, and set the current vertex to the previous vertex, and decrement k
|
||||
while(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second != null){
|
||||
path.add(cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second);
|
||||
v2 = cost_prev_map.get(new Pair<Integer,Integer>(v2,k)).second;
|
||||
k--;
|
||||
}
|
||||
Collections.reverse(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user