0% found this document useful (0 votes)
71 views

Lab Programs

1. The document describes implementing several graph algorithms: Ford-Fulkerson algorithm for finding maximum flow, Johnson's algorithm for all-pairs shortest paths, checking if a graph is bipartite, Rabin-Karp and finite state automata for pattern matching, and Boyer-Moore string matching algorithm. 2. Code examples are provided for Ford-Fulkerson in C++ and Johnson's algorithm in Java, demonstrating how to compute the maximum flow and all-pairs shortest distances respectively. 3. The algorithms are compared in terms of time complexity by measuring the time taken for different input sizes, to analyze their practical efficiency.

Uploaded by

Parinitha B S
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views

Lab Programs

1. The document describes implementing several graph algorithms: Ford-Fulkerson algorithm for finding maximum flow, Johnson's algorithm for all-pairs shortest paths, checking if a graph is bipartite, Rabin-Karp and finite state automata for pattern matching, and Boyer-Moore string matching algorithm. 2. Code examples are provided for Ford-Fulkerson in C++ and Johnson's algorithm in Java, demonstrating how to compute the maximum flow and all-pairs shortest distances respectively. 3. The algorithms are compared in terms of time complexity by measuring the time taken for different input sizes, to analyze their practical efficiency.

Uploaded by

Parinitha B S
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

Advanced Algorithm

1. Implement the Ford Fulkerson algorithm to obtain the maximum possible flow
from source to sink in a given flow network. Analyse the time complexity of
the same by measuring the time taken by the algorithm for different input sizes.
2. Implement the all pair shortest path problem for a directed weighted graph using
Johnson’s algorithm approach in a programming language of your choice.
Analyse the time complexity of the same by measuring the time taken for
different input sizes.
3. Given a graph, write a program to check whether it is a bipartite graph.
4. Implement pattern matching problem using Rabin-karp algorithm and analyse
the time complexity of the same by measuring time taken for different inputs.
5. Implement pattern matching using finite state automata and find the time
taken by it.
6. Implement Boyer Moore algorithm for string matching.
Compare and contrast the algorithms in questions 4,5,6 in terms of practical
space and time complexity(time taken for execution) for different input size.
Analyse the same and comment on the efficiency.
1. Forf Fulkersons Algorithm

// C++ program for implementation of Ford Fulkerson algorithm


#include <iostream>
#include <limits.h>
#include <string.h>
#include <queue>
using namespace std;

// Number of vertices in given graph


#define V 6

/* Returns true if there is a path from source 's' to sink 't' in


residual graph. Also fills parent[] to store the path */
bool bfs(int rGraph[V][V], int s, int t, int parent[])
{
// Create a visited array and mark all vertices as not visited
bool visited[V];
memset(visited, 0, sizeof(visited));

// Create a queue, enqueue source vertex and mark source vertex


// as visited
queue <int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;

// Standard BFS Loop


while (!q.empty())
{
int u = q.front();
q.pop();

for (int v=0; v<V; v++)


{
if (visited[v]==false && rGraph[u][v] > 0)
{
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}

// If we reached sink in BFS starting from source, then return


// true, else false
return (visited[t] == true);
}

// Returns the maximum flow from s to t in the given graph


int fordFulkerson(int graph[V][V], int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
int rGraph[V][V]; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if
there
// is an edge. If rGraph[i][j] is 0, then there is
not)
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];

int parent[V]; // This array is filled by BFS and to store path

int max_flow = 0; // There is no flow initially

// Augment the flow while tere is path from source to sink


while (bfs(rGraph, s, t, parent))
{
// Find minimum residual capacity of the edges along the
// path filled by BFS. Or we can say find the maximum flow
// through the path found.
int path_flow = INT_MAX;
for (v=t; v!=s; v=parent[v])
{
u = parent[v];
path_flow = min(path_flow, rGraph[u][v]);
}

// update residual capacities of the edges and reverse edges


// along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[u][v] -= path_flow;
rGraph[v][u] += path_flow;
}

// Add path flow to overall flow


max_flow += path_flow;
}

// Return the overall flow


return max_flow;
}

// Driver program to test above functions


int main()
{
// Let us create a graph shown in the above example
int graph[V][V] = { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}
};

cout << "The maximum possible flow is " << fordFulkerson(graph, 0, 5);

return 0;
}

//OUTPUT

The maximum possible flow is 23

2. Johnsons Algorithm

import java.util.InputMismatchException;
import java.util.Scanner;
public class JohnsonsAlgorithm
{
private int SOURCE_NODE;
private int numberOfNodes;
private int augmentedMatrix[][];
private int potential[];
private BellmanFord bellmanFord;
private DijkstraShortesPath dijsktraShortesPath;
private int[][] allPairShortestPath;

public static final int MAX_VALUE = 999;

public JohnsonsAlgorithm(int numberOfNodes)


{
this.numberOfNodes = numberOfNodes;
augmentedMatrix = new int[numberOfNodes + 2][numberOfNodes + 2];
SOURCE_NODE = numberOfNodes + 1;
potential = new int[numberOfNodes + 2];
bellmanFord = new BellmanFord(numberOfNodes + 1);
dijsktraShortesPath = new DijkstraShortesPath(numberOfNodes);
allPairShortestPath = new int[numberOfNodes + 1][numberOfNodes + 1];
}

public void johnsonsAlgorithms(int adjacencyMatrix[][])


{
computeAugmentedGraph(adjacencyMatrix);

bellmanFord.BellmanFordEvaluation(SOURCE_NODE, augmentedMatrix);
potential = bellmanFord.getDistances();
int reweightedGraph[][] = reweightGraph(adjacencyMatrix);
for (int i = 1; i <= numberOfNodes; i++)
{
for (int j = 1; j <= numberOfNodes; j++)
{
System.out.print(reweightedGraph[i][j] + "\t");
}
System.out.println();
}

for (int source = 1; source <= numberOfNodes; source++)


{
dijsktraShortesPath.dijkstraShortestPath(source, reweightedGraph);
int[] result = dijsktraShortesPath.getDistances();
for (int destination = 1; destination <= numberOfNodes; destination++)
{
allPairShortestPath[source][destination] = result[destination]
+ potential[destination] - potential[source];
}
}

System.out.println();
for (int i = 1; i<= numberOfNodes; i++)
{
System.out.print("\t"+i);
}
System.out.println();
for (int source = 1; source <= numberOfNodes; source++)
{
System.out.print( source +"\t" );
for (int destination = 1; destination <= numberOfNodes; destination++)
{
System.out.print(allPairShortestPath[source][destination]+ "\t");
}
System.out.println();
}
}

private void computeAugmentedGraph(int adjacencyMatrix[][])


{
for (int source = 1; source <= numberOfNodes; source++)
{
for (int destination = 1; destination <= numberOfNodes; destination++)
{
augmentedMatrix[source][destination] = adjacencyMatrix[source]
[destination];
}
}
for (int destination = 1; destination <= numberOfNodes; destination++)
{
augmentedMatrix[SOURCE_NODE][destination] = 0;
}
}

private int[][] reweightGraph(int adjacencyMatrix[][])


{
int[][] result = new int[numberOfNodes + 1][numberOfNodes + 1];
for (int source = 1; source <= numberOfNodes; source++)
{
for (int destination = 1; destination <= numberOfNodes; destination++)
{
result[source][destination] = adjacencyMatrix[source][destination]
+ potential[source] - potential[destination];
}
}
return result;
}

public static void main(String... arg)


{
int adjacency_matrix[][];
int number_of_vertices;
Scanner scan = new Scanner(System.in);

try
{
System.out.println("Enter the number of vertices");
number_of_vertices = scan.nextInt();
adjacency_matrix = new int[number_of_vertices + 1][number_of_vertices + 1];

System.out.println("Enter the Weighted Matrix for the graph");


for (int i = 1; i <= number_of_vertices; i++)
{
for (int j = 1; j <= number_of_vertices; j++)
{
adjacency_matrix[i][j] = scan.nextInt();
if (i == j)
{
adjacency_matrix[i][j] = 0;
continue;
}
if (adjacency_matrix[i][j] == 0)
{
adjacency_matrix[i][j] = MAX_VALUE;
}
}
}

JohnsonsAlgorithm johnsonsAlgorithm = new


JohnsonsAlgorithm(number_of_vertices);
johnsonsAlgorithm.johnsonsAlgorithms(adjacency_matrix);
} catch (InputMismatchException inputMismatch)
{
System.out.println("Wrong Input Format");
}
scan.close();
}
}

class BellmanFord
{
private int distances[];
private int numberofvertices;
public static final int MAX_VALUE = 999;

public BellmanFord(int numberofvertices)


{
this.numberofvertices = numberofvertices;
distances = new int[numberofvertices + 1];
}

public void BellmanFordEvaluation(int source, int adjacencymatrix[][])


{
for (int node = 1; node <= numberofvertices; node++)
{
distances[node] = MAX_VALUE;
}

distances[source] = 0;

for (int node = 1; node <= numberofvertices - 1; node++)


{
for (int sourcenode = 1; sourcenode <= numberofvertices; sourcenode++)
{
for (int destinationnode = 1; destinationnode <= numberofvertices;
destinationnode++)
{
if (adjacencymatrix[sourcenode][destinationnode] != MAX_VALUE)
{
if (distances[destinationnode] > distances[sourcenode]
+ adjacencymatrix[sourcenode][destinationnode])
{
distances[destinationnode] = distances[sourcenode]
+ adjacencymatrix[sourcenode][destinationnode];
}
}
}
}
}

for (int sourcenode = 1; sourcenode <= numberofvertices; sourcenode++)


{
for (int destinationnode = 1; destinationnode <= numberofvertices;
destinationnode++)
{
if (adjacencymatrix[sourcenode][destinationnode] != MAX_VALUE)
{
if (distances[destinationnode] > distances[sourcenode]
+ adjacencymatrix[sourcenode][destinationnode])
System.out.println("The Graph contains negative egde cycle");
}
}
}
}

public int[] getDistances()


{
return distances;
}
}

class DijkstraShortesPath
{
private boolean settled[];
private boolean unsettled[];
private int distances[];
private int adjacencymatrix[][];
private int numberofvertices;

public static final int MAX_VALUE = 999;

public DijkstraShortesPath(int numberofvertices)


{
this.numberofvertices = numberofvertices;
}

public void dijkstraShortestPath(int source, int adjacencymatrix[][])


{
this.settled = new boolean[numberofvertices + 1];
this.unsettled = new boolean[numberofvertices + 1];
this.distances = new int[numberofvertices + 1];
this.adjacencymatrix = new int[numberofvertices + 1][numberofvertices + 1];

int evaluationnode;
for (int vertex = 1; vertex <= numberofvertices; vertex++)
{
distances[vertex] = MAX_VALUE;
}

for (int sourcevertex = 1; sourcevertex <= numberofvertices; sourcevertex++)


{
for (int destinationvertex = 1; destinationvertex <= numberofvertices;
destinationvertex++)
{
this.adjacencymatrix[sourcevertex][destinationvertex]
= adjacencymatrix[sourcevertex][destinationvertex];
}
}

unsettled[source] = true;
distances[source] = 0;
while (getUnsettledCount(unsettled) != 0)
{
evaluationnode = getNodeWithMinimumDistanceFromUnsettled(unsettled);
unsettled[evaluationnode] = false;
settled[evaluationnode] = true;
evaluateNeighbours(evaluationnode);
}
}

public int getUnsettledCount(boolean unsettled[])


{
int count = 0;
for (int vertex = 1; vertex <= numberofvertices; vertex++)
{
if (unsettled[vertex] == true)
{
count++;
}
}
return count;
}

public int getNodeWithMinimumDistanceFromUnsettled(boolean unsettled[])


{
int min = MAX_VALUE;
int node = 0;
for (int vertex = 1; vertex <= numberofvertices; vertex++)
{
if (unsettled[vertex] == true && distances[vertex] < min)
{
node = vertex;
min = distances[vertex];
}
}
return node;
}

public void evaluateNeighbours(int evaluationNode)


{
int edgeDistance = -1;
int newDistance = -1;

for (int destinationNode = 1; destinationNode <= numberofvertices;


destinationNode++)
{
if (settled[destinationNode] == false)
{
if (adjacencymatrix[evaluationNode][destinationNode] != MAX_VALUE)
{
edgeDistance = adjacencymatrix[evaluationNode][destinationNode];
newDistance = distances[evaluationNode] + edgeDistance;
if (newDistance < distances[destinationNode])
{
distances[destinationNode] = newDistance;
}
unsettled[destinationNode] = true;
}
}
}
}

public int[] getDistances()


{
return distances;
}
}
//OUTPUT

Enter the number of vertices


4
Enter the Weighted Matrix for the graph
0030
2000
0701
6000

All pair shortest path is


1 2 3 4
1 0 10 3 4
2 2 0 5 6
3 7 7 0 1
4 6 16 9 0
3. Bipartite Graph

// C++ program to find out whether a


// given graph is Bipartite or not
#include <iostream>
#include <queue>
#define V 4

using namespace std;

// This function returns true if graph


// G[V][V] is Bipartite, else false
bool isBipartite(int G[][V], int src)
{
// Create a color array to store colors
// assigned to all veritces. Vertex
// number is used as index in this array.
// The value '-1' of colorArr[i]
// is used to indicate that no color
// is assigned to vertex 'i'. The value 1
// is used to indicate first color
// is assigned and value 0 indicates
// second color is assigned.
int colorArr[V];
for (int i = 0; i < V; ++i)
colorArr[i] = -1;

// Assign first color to source


colorArr[src] = 1;

// Create a queue (FIFO) of vertex


// numbers and enqueue source vertex
// for BFS traversal
queue <int> q;
q.push(src);

// Run while there are vertices


// in queue (Similar to BFS)
while (!q.empty())
{
// Dequeue a vertex from queue ( Refer http://goo.gl/35oz8 )
int u = q.front();
q.pop();

// Return false if there is a self-loop


if (G[u][u] == 1)
return false;

// Find all non-colored adjacent vertices


for (int v = 0; v < V; ++v)
{
// An edge from u to v exists and
// destination v is not colored
if (G[u][v] && colorArr[v] == -1)
{
// Assign alternate color to this adjacent v of u
colorArr[v] = 1 - colorArr[u];
q.push(v);
}

// An edge from u to v exists and destination


// v is colored with same color as u
else if (G[u][v] && colorArr[v] == colorArr[u])
return false;
}
}

// If we reach here, then all adjacent


// vertices can be colored with alternate color
return true;
}

// Driver program to test above function


int main()
{
int G[][V] = {{0, 1, 0, 1},
{1, 0, 1, 0},
{0, 1, 0, 1},
{1, 0, 1, 0}
};

isBipartite(G, 0) ? cout << "Yes, it is a bipartite graph" : cout << "No";


return 0;
}

//OUTPUT

Yes, it is a bipartite graph


4. String Matching using Rabin Karp

/* Following program is a C implementation of Rabin Karp


Algorithm given in the CLRS book */
#include <stdio.h>
#include <string.h>

// d is the number of characters in the input alphabet


#define d 256

/* pat -> pattern


txt -> text
q -> A prime number
*/
void search(char pat[], char txt[], int q)
{
int M = strlen(pat);
int N = strlen(txt);
int i, j;
int p = 0; // hash value for pattern
int t = 0; // hash value for txt
int h = 1;

// The value of h would be "pow(d, M-1)%q"


for (i = 0; i < M - 1; i++)
h = (h * d) % q;

// Calculate the hash value of pattern and first


// window of text
for (i = 0; i < M; i++) {
p = (d * p + pat[i]) % q;
t = (d * t + txt[i]) % q;
}

// Slide the pattern over text one by one


for (i = 0; i <= N - M; i++) {

// Check the hash values of current window of text


// and pattern. If the hash values match then only
// check for characters on by one
if (p == t) {
/* Check for characters one by one */
for (j = 0; j < M; j++) {
if (txt[i + j] != pat[j])
break;
}

// if p == t and pat[0...M-1] = txt[i, i+1, ...i+M-1]


if (j == M)
printf("Pattern found at index %d \n", i);
}
// Calculate hash value for next window of text: Remove
// leading digit, add trailing digit
if (i < N - M) {
t = (d * (t - txt[i] * h) + txt[i + M]) % q;

// We might get negative value of t, converting it


// to positive
if (t < 0)
t = (t + q);
}
}
}

/* Driver program to test above function */


int main()
{
char txt[] = "BMSCE, Bengaluru, BMSIT, Bengaluru";
char pat[] = "Beng";
int q = 101; // A prime number
search(pat, txt, q);
return 0;
}

//OUTPUT

Pattern found at index 8


Pattern found at index 26
5. String Matching using Finite Automata

// C program for Finite Automata Pattern searching


// Algorithm
#include<stdio.h>
#include<string.h>
#define NO_OF_CHARS 256

int getNextState(char *pat, int M, int state, int x)


{
// If the character c is same as next character
// in pattern,then simply increment state
if (state < M && x == pat[state])
return state+1;

// ns stores the result which is next state


int ns, i;

// ns finally contains the longest prefix


// which is also suffix in "pat[0..state-1]c"

// Start from the largest possible value


// and stop when you find a prefix which
// is also suffix
for (ns = state; ns > 0; ns--)
{
if (pat[ns-1] == x)
{
for (i = 0; i < ns-1; i++)
if (pat[i] != pat[state-ns+1+i])
break;
if (i == ns-1)
return ns;
}
}

return 0;
}

/* This function builds the TF table which represents4


Finite Automata for a given pattern */
void computeTF(char *pat, int M, int TF[][NO_OF_CHARS])
{
int state, x;
for (state = 0; state <= M; ++state)
for (x = 0; x < NO_OF_CHARS; ++x)
TF[state][x] = getNextState(pat, M, state, x);
}

/* Prints all occurrences of pat in txt */


void search(char *pat, char *txt)
{
int M = strlen(pat);
int N = strlen(txt);

int TF[M+1][NO_OF_CHARS];

computeTF(pat, M, TF);

// Process txt over FA.


int i, state=0;
for (i = 0; i < N; i++)
{
state = TF[state][txt[i]];
if (state == M)
printf ("\n Pattern found at index %d", i-M+1);
}
}

// Driver program to test above function


int main()
{
char *txt = "AABAACAADAABAAABAA";
char *pat = "AABA";
search(pat, txt);
return 0;
}

//Output

Pattern found at index 0


Pattern found at index 9
Pattern found at index 13
6. String Matching using Boyer Moore

/* C Program for Boyer Moore String Matching Algorithm */

# include <limits.h>

# include <string.h>

# include <stdio.h>

# define NO_OF_CHARS 256

// A utility function to get maximum of two integers

int max (int a, int b) { return (a > b)? a: b; }

// The preprocessing function for Boyer Moore's

// bad character heuristic

void badCharHeuristic( char *str, int size,

int badchar[NO_OF_CHARS])

int i;

// Initialize all occurrences as -1

for (i = 0; i < NO_OF_CHARS; i++)

badchar[i] = -1;

// Fill the actual value of last occurrence

// of a character

for (i = 0; i < size; i++)

badchar[(int) str[i]] = i;

/* A pattern searching function that uses Bad Character Heuristic of Boyer Moore
Algorithm */

void search( char *txt, char *pat)

int m = strlen(pat);

int n = strlen(txt);

int badchar[NO_OF_CHARS];
/* Fill the bad character array by calling

the preprocessing function badCharHeuristic()

for given pattern */

badCharHeuristic(pat, m, badchar);

int s = 0; // s is shift of the pattern with

// respect to text

while(s <= (n - m))

int j = m-1;

/* Keep reducing index j of pattern while

characters of pattern and text are

matching at this shift s */

while(j >= 0 && pat[j] == txt[s+j])

j--;

/* If the pattern is present at current

shift, then index j will become -1 after

the above loop */

if (j < 0)

printf("\n pattern occurs at shift = %d", s);

/* Shift the pattern so that the next

character in text aligns with the last

occurrence of it in pattern.

The condition s+m < n is necessary for

the case when pattern occurs at the end

of text */

s += (s+m < n)? m-badchar[txt[s+m]] : 1;

else

/* Shift the pattern so that the bad character

in text aligns with the last occurrence of


it in pattern. The max function is used to

make sure that we get a positive shift.

We may get a negative shift if the last

occurrence of bad character in pattern

is on the right side of the current

character. */

s += max(1, j - badchar[txt[s+j]]);

/* Driver program to test above funtion */

int main()

char txt[] = "ABAAABCD";

char pat[] = "ABC";

search(txt, pat);

return 0;

//Output

pattern occurs at shift = 4

Measuring time taken by programs

1. C Programming

#include <time.h>

clock_t start, end;


double cpu_time_used;

start = clock();
... /* Do the work. */
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

2. C++ Programming

#include <chrono>
using namespace std::chrono;

auto start = high_resolution_clock::now();


auto stop = high_resolution_clock::now();

auto duration = duration_cast<microseconds>(stop - start);

cout << duration.count() << endl;

3. Java Programming

import java.io.*;

long start = System.currentTimeMillis();

long end = System.currentTimeMillis();

System.out.println("Counting to 10000000 takes "+ (end - start) + "ms");

You might also like