Skip to content

Latest commit

 

History

History
304 lines (276 loc) · 11.4 KB

README.md

File metadata and controls

304 lines (276 loc) · 11.4 KB

CircuitSwitching

/** PROJECT DETAILS

  • Authors : Soham Kapur, Koushiki Sinha
  • Year : 2023
  • Title : Circuit Switching using Dynamic Programming
  • Purpose : Undergraduate Graded Project
  • Course : Computer Networks
  • Desc : Simulation of Circuit Switching in Java to find optimal set of paths for multiple data transfers using Dynamic Programming. */

/* VARIABLES: * n: Number of data transfers * k: Counter for current Source and Destination pair being checked * s: Array to store all Souce nodes. * d: Array to store all Destination nodes. * min: Stores the minimum Longest path distance of the checked combinations ofpaths. */

//CODE BEGINS HERE:

import java.util.*; public class CircuitSwitching { ArrayList[] adjList; static int n=0, k=0, s[], d[], min=Integer.MAX_VALUE;

int Graph[][] = { { 0, 4, 0, 0, 0, 0, 0, 8, 0 },
        { 4, 0, 8, 0, 0, 0, 0, 11, 0 },
        { 0, 8, 0, 7, 0, 4, 0, 0, 2 },
        { 0, 0, 7, 0, 9, 14, 0, 0, 0 },
        { 0, 0, 0, 9, 0, 10, 0, 0, 0 },
        { 0, 0, 4, 14, 10, 0, 2, 0, 0 },
        { 0, 0, 0, 0, 0, 2, 0, 1, 6 },
        { 8, 11, 0, 0, 0, 0, 1, 0, 7 },
        { 0, 0, 2, 0, 0, 0, 6, 7, 0 } };

/* * This is the Graph (Network) consisting of nodes and edges expressed as an Adjacency Matrix, using a DDA. * The index value represents the nodes and the array elements at the coordinates represent the Edge weight between the 2 nodes. * The edge with direction from node u to node v will be at Graph[u][v]. * The sample graph used here is an Undirected Graph, but a Directed Graph can also be used without any other change in the code. */

//This copy of the graph is created so that the user can use this code in a loop (not present in this code) without changing the original Graph.
int altGraph[][] = Graph;
//The mpdifications to the original Graph present in the Alternate Graph (altGraph) will be explained later in the code.

int v = Graph[0].length;
boolean visited[] = new boolean[v];
static ArrayList<ArrayList<Integer>>[] allPaths; 
//Data structure to store all possible paths between 2 nodes

static ArrayList<Integer>[] distances;
//Data structure to store total distance or weight of each path between 2 given nodes

static ArrayList<Integer>[] FinalPaths; 
//Data Structure to store the final set of paths that should be chosen

// Constructor to initialise 'v', the number of nodes
public CircuitSwitching()
{
    this.v = v;
    initAdjList();
}

// utility method to initialise adjacency lists
void initAdjList()
{
    int i;
    adjList = new ArrayList[v];
    for (i = 0; i < v; i++)
        adjList[i] = new ArrayList<>();

    allPaths = new ArrayList[n];
    for(i=0; i<n; i++)
        allPaths[i] = new ArrayList<>();

    distances = new ArrayList[n];

    FinalPaths = new ArrayList[n];
    for(i=0; i<n; i++)
        FinalPaths[i] = new ArrayList<>();
}

/* The graph is transferred from a DDA to an Array of ArrayLists.
 * This prevents checking of pairs of nodes that do not have any edge, thus improving speed in the following operations.
 */
public void addEdges()
{
    int n=v;
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            if(Graph[i][j]>0)
                adjList[i].add(j);
}

/* In the alternate graph, all incoming edges of every Source node and all outgoing edges of every Destination node are eliminated.
 * This reduces the number of edges that the program has to check, thus improving speed and efficiency.
 */
public void AltGraph()
{
    for(int i=0; i<n; i++)
        for(int j=0; j<9; j++)
        {
            altGraph[j][s[i]] = 0;
            altGraph[d[i]][j] = 0;
        }
}

// Parts of this function have been taken from the code for finding All Paths in a Graph, available on "Geeks For Geeks" 
public void getAllPaths(int s, int d)
{
    boolean[] isVisited = new boolean[v];
    ArrayList<Integer> pathList = new ArrayList<>();
    // add source to path[]
    pathList.add(s);
    // Call utility function
    getAllPathsUtil(s, d, isVisited, pathList, 0);
}

// Parts of this function have been taken from the code for finding All Paths in a Graph, available on "Geeks For Geeks" 
private void getAllPathsUtil(Integer u, Integer d, boolean[] isVisited, ArrayList<Integer> localPathList, int distance)
{
    /* An if condition that prevents the checking of some extra paths by terminating the recursion if the destination node is adjacent to the current node.
     * This prevents the checking of some useless paths and saves time.
     * It assumes that the direct edge between any two nodes is the shortest possible path between them.
     * This condition is only useful when all edges have positive weights.
     */
    if(altGraph[u][d]>0)
    {
        localPathList.add(d);
        allPaths[k].add(new ArrayList<>(localPathList));
        distances[k].add(distance + altGraph[u][d]);
        localPathList.remove(d);
        return;
    }
    isVisited[u] = true;
    // This loop having recursion checks the possibility of creating a path between the Source and Destination using every node.
    for (Integer i : adjList[u])
    {
        if (!isVisited[i])
        {
            // store current node in path
            localPathList.add(i);
            distance += altGraph[u][i];
            getAllPathsUtil(i, d, isVisited, localPathList, distance);
            distance -= altGraph[u][i];
            // remove current node in path
            localPathList.remove(i);
        }
    }
    isVisited[u] = false;
}

//This function uses Bubble Sort to sort the paths between every pair of Source and Destination nodes with respect to total distance/weight.
void sortPaths()
{
    for(int h=0; h<n; h++)
    {    
        int l = allPaths[h].size();
        for (int i = 0; i < l-1; i++)
            for (int j = 0; j < l-i-1; j++)
                if (distances[h].get(j) > distances[h].get(j+1))
                {
                    Collections.swap(allPaths[h], j, j+1);
                    Collections.swap(distances[h], j, j+1);
                }
    }
}

//This function prints all the paths between every pair of Source and Destination nodes and their respective total distances. 
public void printPaths()
{
    for(int i=0; i<n; i++)
    {
        System.out.println("\nAll paths from " + s[i] + " to " + d[i] + " are:");
        System.out.println("\tDistance\tPaths");
        for(int j=0; j<allPaths[i].size(); j++)
            System.out.println("\t   " + distances[i].get(j) + "\t\t" + allPaths[i].get(j));
    }
}

/* This is the function where the Dynamic Programming takes place.
 * This function iterates through all possible combinations of paths.
 * It returns the combination in which the Longest path is the smallest as compared to the Longest Paths in other combinations.
 * Other conditions, such as Smallest Mean, Smallest Median or other statistical values using all paths in a combination, can also be used as required.
 * The program will have to be modified to accomodate other or more conditions.
 * The purpose of this function is to find the most optimal combination of paths as per the set condition for optimality.
 */
void AltPaths(int p, int max, ArrayList<Integer>[] finalPath)
{
    if(p==n)
    {
        // This is the if statement that finalises the combination based on the set condition.
        if(min>max)
        {
            System.out.println();
            min = max;
            finalise(finalPath);
            System.out.println(finalPath);
        }
        return;
    }
    int i, j, l = allPaths[p].size();
    //This loop recursively creates all combinations of paths to ultimately check the optimality condition.
    for(i=0; i<l; i++)
    {
        if(checkIntersect(allPaths[p].get(i)))
            continue;
        visit(allPaths[p].get(i), p);
        max = Math.max(max, distances[p].get(i));
        finalPath[p] = new ArrayList<>();
        finalPath[p] = allPaths[p].get(i);
        AltPaths(p+1, max, finalPath);
        unvisit(finalPath[p], p);
        finalPath[p].clear();
    }
}

//This function checks if any node in the selected path is already present in a previously selected path.
boolean checkIntersect(ArrayList<Integer> path)
{
    for(int i=1; i<path.size()-1; i++)
        if(visited[path.get(i)])
            return true;
    return false;
}

// This functions visits all nodes in a path so that they can be checked for intersection of another path.
void visit(ArrayList<Integer> path, int p)
{
    for(int i=1; i<path.size()-1; i++)
        visited[path.get(i)] = true;
}

// This function 'unvisits' all nodes in a path once that paths is deleted from the current combination.
void unvisit(ArrayList<Integer> path, int p)
{
    for(int i=1; i<path.size()-1; i++)
        visited[path.get(i)] = false;
}

// This function adds the selected combination to a global variable to be accessed later on.
void finalise(ArrayList<Integer>[] finalPath)
{
    for(int i=0; i<n; i++)
        FinalPaths[i] = new ArrayList<>(finalPath[i]);
}

// This funciton prints the finalised combination, and if there is no data then prints the appropriate message.
void printFinal()
{
    System.out.println("Max distance: " + min + "\nFinal list of paths is: ");
    for(int i=0; i<n; i++)
    {
        if(FinalPaths[i].size()==0)
        {
            System.out.println("The given data transfers cannot occur simultaneously.");
            break;
        }
        else
            System.out.println(FinalPaths[i]);
    }
}

// Driver code
// This code was written in BlueJ which does not require the "String[] args" parameter.
// If compiling in another terminal, write as "main(String[] args)".
public static void main()
{
    Scanner sc = new Scanner(System.in);
    System.out.println("Enter no. of paths to travel:");
    n = sc.nextInt();
    s = new int[n];
    d = new int[n];
    ArrayList <Integer>[] finalPath = new ArrayList[n];
    int i, j;
    for(i=0; i<n; i++)
        finalPath[i] = new ArrayList<>();

    CircuitSwitching g = new CircuitSwitching();
    for(i=0; i<n;i++)
    {
        System.out.println("Enter Source " + (i+1) + ":");
        s[i] = sc.nextInt();
        System.out.println("Enter Destination " + (i+1) + ":");
        d[i] = sc.nextInt();
    }
    g.AltGraph();
    g.addEdges();
    for(i=0; i<n; i++)
    {
        k=i;
        distances[i] = new ArrayList<>();
        g.getAllPaths(s[i], d[i]);
    }
    System.out.println("\n\nSorted Paths: ");
    g.sortPaths();
    g.printPaths();
    System.out.println("\n");
    g.AltPaths(0, 0, finalPath);
    g.printFinal();
}

}