design & analysis of algorithms - wordpress.com how to compile your code to compile and build...

135
Design & Analysis of Algorithms Laboratory Instructions & Assignments By: Prof. Sourav Saha Prof. Pinaki karmakar

Upload: trinhquynh

Post on 03-Apr-2018

233 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Design & Analysis of Algorithms

Laboratory Instructions & Assignments By: Prof. Sourav Saha Prof. Pinaki karmakar

iem
Text Box
CS 591
Page 2: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Divide & Conquer: Binary Search, Merge Sort, Quick Sort

WEEK 1

Page 3: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

3

Familiarize with your lab environment

To start working in the Design & Analysis of Algorithms Lab, you need to login to your student account, and then cd to the algo_lab directory. This is your base working directory.

In this directory you will find four sub-directories lib, bin, src and inc

The bin directory would be used to store your executable, and the lib directory would be used to store the c library that you will create

The src directory would contain all the .c files (c source code) that you will write in this lab

The inc directory would contain all the .h (#include) files that you would be writing

Page 4: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

4

How to compile your code

To compile and build the executable type ./build in the algo_lab directory.

./build

This will compile your c source code, and if there are no errors, create the executable file named demo in the algo_lab/bin directory.

As an example the Linear Search algorithm has been implemented, so when you run the executable, you will be able to test the Linear Search algorithm.

Page 5: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

5

How to execute your code

To execute your code, cd to algo_lab/bin directory

cd bin

Here you will find a file named demo

Type ./demo now

./demo

You will find the following Menu in your screen

WELCOME TO THE DESIGN AND ANALYSIS OF ALGORITHMS LAB

Main Menu

01. Linear Search

99. Exit

Type 1 here and you will be able to execute and test the Linear Search algorithm

Enter Your Choice:

Page 6: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

6

How to add your menu item

As you would have noticed, currently you have only one menu item 01. Linear Search

Let’s say we want to add another menu item for Binary Search, then we will need to update the following files.

cd to the src directory, open the MenuItemAdder.c file in editor.

vi MenuItemAdder.c

This file contains only one function with the following code:

void addMenuItems() { This is the name of the menu item, which is displayed

addMenu("Linear Search", lsearchdemo);

} This is the name of the function which will be called when the menu item is selected

Page 7: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

7

How to add your menu item

To add another menu item for Binary Search, add the following line of code in the addMenuItems() function:

void addMenuItems() {

addMenu("Linear Search", lsearchdemo);

addMenu(“Binary Search”, bsearchdemo); This line of code needs to be added

}

Save your code now. This will add a new menu item, named Binary Search in the menu, and when the user chooses this menu item bsearchdemo function is called.

You might wonder who would write the bsearchdemo function? The answer is of course you.

This function needs to be placed in the AlgoLab.c file. So this file needs to be edited next.

Page 8: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

8

How to add your menu item

Open the AlgoLab.c file in editor.

vi AlgoLab.c

You will see that there is a function named lsearchdemo() in this file, this is the function, which is called when the Linear Search menu item is selected.

Add another method named bsearchdemo() in this file, this function must return nothing (void) and take no arguments.

void bsearchdemo() {

// your code here

}

Keep this function empty for now

Save your code.

Remember the entry you added in MenuItemAdder.c addMenu(“Binary Search”, bsearchdemo); The second argument of addMenu, bsearchdemo, is the name of the function which is called when the menu item is selected. We call it the menu callback function. Here, you are providing the implementation of the menu callback function. So you need to make sure that the 2nd argument of addMenu and the name of this function here are same.

Page 9: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

9

How to add your menu item

There is only one more step before we can see our menu item. We need to put the signature of the bsearchdemo() function in the algo_lab/inc/AlgoLab.h file

cd to inc directory and open the AlgoLab.h file in editor

vi AlgoLab.h

You will see the following code in this file

#ifndef _ALGOLAB_H_

#define _ALGOLAB_H_

void lsearchdemo();

#endif

Page 10: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

10

How to add your menu item

Add the signature of the bsearchdemo() function in this file

#ifndef _ALGOLAB_H_

#define _ALGOLAB_H_

void lsearchdemo();

void bsearchdemo();

this line needs to be added

#endif

• Save your change and now you are ready to test your new menu item.

• Compile your code (refer to page 4)

• Test your code (refer to page 5)

Page 11: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

11

How to add your menu item

Now you would see two menu items instead of one.

WELCOME TO THE DESIGN AND ANALYSIS OF ALGORITHMS LAB

Main Menu

01. Linear Search

02. Binary Search

99. Exit

Enter Your Choice:

Page 12: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

12

How to implement your algorithm

You might have noticed that we haven’t discussed about implementing the binary search algorithm so far. So let us see how to implement it.

cd to the algo_lab/src/algorithms directory

You will find a file named LinearSearch.c, this file implements the LinearSearch algorithm

We will now create a new file named BinarySearch.c, which will contain the implementation of the Binary Search algorithm.

int binarySearch(int a[], int l, int r, int key) { // binary search for key in a[l … r]

if (key < a[l] || key > a[r]) return -1; // key is not found

int m = (l + r) / 2; // m is the mid-point of a

if (key < a[m]) return binarySearch(a, l, m – 1, key); // (binary) search in the left half

else if (key > a[m]) return binarySearch(a, m + 1, r, key); // (binary) search in the right half

else return m; // found the key

}

Page 13: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

13

Update the file information

Before you save your code you need to update the file information, at the beginning of your .c file.

//- - -- -- - -- - -- - -- -- - -- - -- - -- -- - -- - -- -- - -- - -- - -- -- - -- - --- - -- -- - -- - -- -- - -- - -- - -- -- - -- - -- - -- -- - -- - -- -- - -

//

// Course : Design & Analysis of Algorithm Lab

// Code : CS591

// Assignment Number : <Write the assignment number, e.g. 1.1>

// Author(s) : <Write your name>

// Roll Number(s) : <Write your roll number>

// Date : <Write the date of implementation>

//

//- - -- -- - -- - -- - -- -- - -- - -- - -- -- - -- - -- -- - -- - -- - -- -- - -- - --- - -- -- - -- - -- -- - -- - -- - -- -- - -- - -- - -- -- - -- - -- -- - -

Save your code now.

Page 14: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

14

Create the corresponding header file

cd to the algo_lab/inc/algorithms directory

You will find a file named LinearSearch.h, this file defines the LinearSearch algorithm

We will now create a new file named BinarySearch.h, which will contain the definition of the Binary Search algorithm.

#ifndef _BINARYSEARCH_H_

#define _BINARYSEARCH_H_

int binarySearch(int a[], int l, int r, int key);

#endif

Page 15: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

15

Update the Makefile

Of course now, we would like to compile our newly added code. Follow the steps below before you go for compilation.

cd to the algo_lab/src/algorithms directory, you will find a file named Makefile there. Open this file in editor.

vi Makefile

Find the line SRC = LinearSearch.c in this file.

Edit the file to add the entry for BinarySearch.c in the following manner:

SRC = LinearSearch.c \ ←add a “slash” in this line

BinarySearch.c ←add the entry for BinarySearch.c without a slash

Save your changes.

Page 16: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

16

Call your algorithm from the menu callback

Now, we are ready to add code to our bsearchdemo method (remember that we had left it

empty). cd to the /home/student/algo_lab/src directory and edit the AlgoLab.c file

Include the BinarySearch.h file

#include <algorithms/BinarySearch.h>

In the bsearchdemo() function add the code to read an array of elements and the key to be searched from the user (refer to the lsearchdemo function as example).

Now call the binarySearch function that you implemented in BinarySearch.c from bsearchdemo() (just like the find function is called from the lsearchdemo() function).

void bsearchdemo() {

// read an array a of n elements and a key

int found = binarySearch(a, 0, n – 1, key);

// print whether the key was found or not

}

Save your changes.

Compile & test your code (refer to page 4, 5)

Page 17: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

17

Where is my main() function?

• Cheer up! You DO NOT need to write the C main() function in this lab.

• The intention of this lab is to make you focus

on writing algorithms, and not to teach C.

• We have taken care to write the main function for you, so that you do not have to bother about such small matters.

• So, do what you do best, which is to implement

(in your humble opinion) best-in-class, state-of-the-art, cutting-edge algorithms.

• Just follow the steps in the next page each time

you implement a new algorithm and you will rock!!!

Page 18: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

18

Summary

To add a new algorithm and a corresponding menu item:

1. Add an entry for the new menu item in algo_lab/src/MenuItemAdder.c (page 6, 7)

2. Add the corresponding menu callback function (e.g. myalgodemo) in algo_lab/src/AlgoLab.c (page 8)

3. Add the definition of the menu callback function in algo_lab/inc/AlgoLab.h (page 9, 10)

4. Create a new .c file (e.g. MyAlgo.c) in algo_lab/src/algorithms directory. Implement your algorithm in this file, as one or more c functions and don’t forget to update the file information. (page 12, 13)

5. Add the definition of the functions implemented in previous step in a new .h file (e.g. MyAlgo.h) in algo_lab/inc/algorithms directory (page 14)

6. Add the entry for your MyAlgo.c file in the SRC = section of the Makefile in algo_lab/src/algorithms directory. You should add your entry in the end (last line) of the section, and remember to add a slash (\) in the previous line. (page 15)

7. Implement the menu callback function (myalgodemo). You should read the inputs for your algorithm from the user here and then call the function in MyAlgo.c which implements your algorithm (page 16)

8. Compile and test your code (page 4, 5).

Page 19: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Assignments 19

1.1 Implement the quick sort algorithm 1.2 Implement the merge sort algorithm

quickSort(A, l, r) mergeSort(A, l, r)

if l < r if l < r

p = partition(A, l, r) m = (l + r) / 2

quickSort(A, l, p - 1) mergeSort(A, l, m)

quickSort(A, p + 1, r) mergeSort(A, m + 1, r)

merge(A, l, m, r)

partition(A, l, r)

pivot = A[r] merge(A, l, m, r)

i = l – 1 i = l, j = m + 1, B[r – l + 1]

for j = l to r – 1 for k = 0 to r - l

if A[j] ≤ pivot if j > r B[k] = A[i++]

i = i + 1 else if i > m B[k] = A[j++]

exchange A[i], A[j] else if A[i] < A[j] B[k] = A[i++]

exchange A[i + 1], A[r] else B[k] = A[j++]

return i + 1 for k = 0 to r - l A[l + k] = B[k]

Page 20: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Dynamic Programming: Matrix Chain Multiplication

WEEK 2

Page 21: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

21

Matrix Chain Multiplication

• Let us suppose that we are given a chain of n matrices A1, A2, …, An and we

have to calculate the matrix product P, such that P = A1A2…An

• 3) time. • Thus if two matrices A & B of dimensions (p x q) and (q x r) would require

p.q.r scalar multiplications.

• Our intension is to multiply n matrices A1, A2, …, An to find their product P, such that the number of scalar multiplications are minimum.

• Suppose A, B & C are 3 matrices, then their product P can be calculated as P

= (A.B).C = A.(B.C) • That is, multiplying A with B first and then multiplying their product with C

gives the same result as multiplying B with C first and then multiplying their product with A.

• But the way we parenthesize this operation has a big impact on the number

of scalar multiplications required to compute the product.

Page 22: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Calculating the number of scalar

22

multiplications

• Suppose the dimensions of A, B & C are given as (1 x 2), (2 x 5) & (5 x 1) respectively.

• If we find their product as (A.B).C then the number of scalar

multiplications needed are 1.2.5 + 1.5.1 = 15 • If we find their product as A.(B.C) then the number of scalar

multiplications needed are 2.5.1 + 1.2.1 = 12 • Thus we observe that parenthesizing the matrices as A.(B.C) evaluates

their product with less scalar multiplications. • The matrix chain multiplication problem can be restated as follows:

• Given n matrices A1, A2, …, An of dimensions (p0 x p1), (p1 x p2), …, (pn-1 x

pn) respectively, we have to fully parenthesize the product P = A1A2…An in such a way that it minimizes the number of scalar multiplications.

Page 23: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

The structure of optimal solution

23

• Let Ai,j denote the matrix product AiAi+1…Aj • Let us suppose that there is an integer k, such that if we parenthesize the product Ai,j as

(AiAi+1…Ak). (Ak+1…Aj) the number of scalar multiplications are minimum.

• Clearly to compute Ai,j one has to compute the product matrices Ai,k = (AiAi+1…Ak)

and Ak+1,j = (Ak+1…Aj) and then multiply them. • Since the dimension of Ai is (pi-1 x pi) the dimensions of Ai,k & Ak+1,j would be (pi-

1 x pk) and (pk x pj) respectively.

• Hence multiplication of Ai,k & Ak+1,j would require pi-1pkpj scalar multiplications.

• Let m(i, j) be the optimal cost for multiplying matrices AiAi+1…Aj i.e. computing Ai,j

• Since computation of Ai,j requires computation of Ai,k & Ak+1,j and then pi-1pkpj scalar multiplications for evaluating their product, we have:

• m(i, j) = m(i, k) + m(k + 1, j) + pi-1pkpj

• Clearly m(i, i) = 0 & m(i, i + 1) = pi-1pipi+1 • The above recurrence relation assumes that we know the value of k, which we do

not, hence we need to check it for all possible values of k, where i ≤ k < j

Page 24: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

24

A recursive solution

• The matrix chain multiplication problem can be solved by the following recurrence:

m(i, j) = 0 if j = i

= p

i-1p

i p

i+1 if j = i + 1

= min{ m(i, k) + m(k + 1, j) + pi-1pkpj } if j > i + 1 i ≤ k < j

• For example, say we want to multiply 4 matrices: (1 x 2), (2 x 3), (3 x4), (4 x 1). Our recursive approach will lead to the following recursion tree:

m(1, 4)

m(1, 1), m(2, 4) m(1, 2), m(3, 4) m(1, 3), m(4, 4)

m(2, 2), m(3, 4) m(2, 3), m(4, 4) m(1, 1), m(2, 3) m(1, 2), m(3, 3)

• As we can see, this is a top down approach, i.e. that is we start with a call to m(1, 4) and then go down the tree until we find a node, whose value is known (e.g. m(1, 1))

• The problem with this approach is that the same values are evaluated again and

again, e.g. m(1, 2) is computed twice above, as is m(2, 3) and m(3, 4)

Page 25: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

25

Dynamic Programming: Bottom-up Approach

• The idea behind dynamic programming is to build the solution in a bottom-up manner, and re-use the previously computed values in order to compute a new one.

• Looking at our example we need to find m(1, 4), i.e. a product of a matrix-chain of

length 4. We start from the product of the matrix-chain of length 0, i.e. m(1, 1), m(2, 2), m(2, 3), m(4, 4) and the product of the matrix-chain of length 1, i.e. m(1, 2), m(2, 3), m(3, 4) whose values are already known.

• Let us build a table of size n x n (4 x 4 in our example), where the entry (i, j) indicates

the number of multiplications required to compute the product of a chain of matrices from Ai to Aj. For example the entry (2, 4) in the table would give us the number of scalar

multiplications to compute the product of A2 to A4 • We are of course interested in the entries on and above the diagonal. • So, filling the table with the already known values:

0 6 Matrix chain Product of: A1x2 B2x3 C3x4 & D4x1

m(1, 1) = m(2, 2) = m(3, 3) = m(4, 4) = 0

0 24

m(1, 2) = 1.2.3 = 6

0 12 m(2, 3) = 2.3.4 = 24

m(3, 4) = 3.4.1 = 12

0

Page 26: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

26

Filling the table

• The next step is to compute the number of scalar multiplications needed for evaluating products of matrix chains of length 2, i.e. m(1, 3) and m(2, 4) in our example.

m(1,1) m(2,3) 1.2.4 0 24 8

m(1,3) min min 18

6 0 12

m(1,2) m(3,3) 1.3.4

m(2,4) min

m(2,2) m(3,4) 2.3.1

min

0 12 6

18

24 0 8

m(2,3) m(4,4) 2.4.1

• Filling these entries in the table gives us:

0 6 18

0 24 18

0 12

0

Page 27: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

27

Computing m(1, 4)

• Finally, the value of m(1, 4) is computed as:

m(1,1) m(2,4) 1.2.1 0 18 2

m(1,4) minm(1,2) m(3,4) 1.3.1 min 6 12 3 20

m(4,4)

4

m(1,3) 1.4.1 18 0

• So, we fill the final and desired entry in the table:

0 6 18 20

0 24 18

0 12

0 • Thus the minimum number of scalar multiplications to compute our matrix

product of the chain of 4 matrices is 20.

Page 28: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

28

Assignment 2.1

• Implement the dynamic programming algorithm for matrix chain multiplications

mcm() // computes the least number of scalar multiplications to multiply a chain of matrices for (i = 1 to n)

m[i][i] = 0;

if (i ≠ n) m[i][i + 1] = p[i-1]*p[i]*p[i+1]; for (l = 2 to n - 1)

for (i = 1 to n - l )

j = i + l; m[i][j] = ∞; for (k = i to j - 1)

q = m[i][k] + m[k + 1][j] + p[i-1]*p[k]*p[j]; if (q < m[i][j])

m[i][j] = q; s[i][j] = k;

return m[1][n];

mcorder(s[][n], i, j) // prints the matrix chain order, initial call should be mcorder(s, 1, n) if (i == j) print(“Ai”); else if (j == i + 1) print("(Ai.Aj)"); else

print("(");

mcorder(s, i, s[i][j]); mcorder(s, s[i][j] + 1, j); print(")");

Page 29: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Graph & Graph Algorithms

WEEK 3

Page 30: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

30

Definitions & Terminology

• A graph is a practical representation of the relationship between some objects, represented in a 2D diagram.

• The set of objects [V = {v1, v2, …}] are called vertices and are

represented in 2D by points. • The set of relationships [E = {e1, e2, …}] between the objects are called

edges and are represented on 2D by lines. • Every edge ek, is associated with a pair of vertices vi & vj, which are

called the end-vertices of ek.

v2

v4

v1

v3

Page 31: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

31

Adjacency Matrix representation of a Graph

• A graph G = (V, E) Can be represented by an Adjacency matrix A = [Aij] according to the following rules:

• Aij = 1, if there is an edge between vertex i, j

• Aij = 0, if there is no edge between vertex i, j

• For example the graph below can be represented by its adjacency matrix:

v1 v2 v3 v4

v2 v1 0 1 1 0

v2 1 0 1 1

v4

v1 v3 1 1 0 1

v3 v4 0 1 1 0

Page 32: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

32

Assignment 3.1: Reading Graph from a file

• Suppose you are given with a file with n lines, each line contains exactly n integers separated by TAB. For example:

0 1 1 1 0 0

Represents

1 0 0 0 1 1 v1

this graph

1 0 0 0 0 0

1 0 0 0 0 0

0 1 0 0 0 0

0 1 0 0 0 0

v2 v3 v4

v5 v6

• The file above has 6 lines and each line contains 6 numbers, separated by TAB.

• Read the file, and instantiate a two dimensional array of size n x n

Page 33: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

(6 x 6) in this example.

Page 34: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

33

Guideline • We will create a function, say readGraph(), which takes two parameters a FILE pointer fp and a 2D

array G[][n], n being the number of vertices in the graph. The function will read the file pointed to by fp, and fill-up entries of G.

• The first task in hand is to read a file one line at a time. The getline() function in C can be used to achieve

this. • Then we need to tokenize the line (which contains n integers separated by TAB). The strsep() function

can help us achieve it. • Finally, each token, as read from the file, is received as a pointer to characters, we need to convert it to

int using the atoi() function.

void readGraph(FILE* fp, int G[][n]) {

char* line = NULL; size_t size; int i = 0;

while (getline(&line, &size, fp) != -1) { // read a line from the file

char* edge; int j = 0;

while ((edge = strsep(&line, "\t")) != NULL) G[i][j++] = atoi(edge); // read an edge

i++;

}

}

Page 35: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

34

Assignment 3.2: Reading Edges from the Adjacency Matrix of a Graph

• Suppose you are given a weighted adjacency matrix G of a graph. For example:

0 5 3 ∞

Represents

5 0 2 1

this graph v2

3 2 0 4 5 1

v1

2 v4

∞ 1 4 0

4

3

v3

• The adjacency matrix is given to you as a 2D array G[n][n], and you want to parse it and create an array of structures, which represent the edges of the graph.

• You need to avoid duplicate entries for undirected graphs. For example,

in this graph (1, 2) and (2, 1) represent the same edge. So you should report only one edge instead of two.

• Use the value 999999 to represent ∞.

Page 36: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

35

Guideline

• The first task is to create the struct edge. We will use the following definition:

typedef struct Edge {

int u; // represents the first end-vertex of the edge int v;

// represents the second end-vertex of the edge int cost;

// represents the cost/weight of the edge

} edge;

• Now, let us create a function getEdges(), which takes two parameters, the (weighted) adjacency matrix of the graph G, and an array edges of struct edge (which is empty). The function will parse G and fill-up the entries in edges. Here is the pseudo-code.

getEdges(G[][n], edges[])

k = 0; // number of edges in the graph

for i = 0 to n - 1

for j = 0 to n - 1

if G[i][j] ≠ 0 AND G[i][j] ≠ ∞ // check if an edge exists

if j > i OR G[i][j] ≠ G[j][i] // avoid duplication

edge e;

e.u = i; e.v = j; e.cost = G[i][j]; // fill the details of the edge

edges[k++] = e;

return k; // how many edges were found?

Page 37: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

36

Traversing a Graph

• One of the most fundamental graph problem is to traverse a graph. • We have to start from one of the vertices, and then mark each vertex when

we visit it. For each vertex we maintain three flags:

– Unvisited – Visited but unexplored

– Visited and completely explored • The order in which vertices are explored depends upon the kind of

data structure used to store intermediate vertices.

– Queue (FIFO) – Stack (LIFO)

Page 38: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

37

Breadth First Search (BFS)

• In this technique we start from a given vertex v and then mark it as visited (but not completely explored).

• A vertex is said to be explored when all the vertices adjacent to it are visited. • All vertices adjacent to v are visited next, these are new unexplored vertices. • The vertex v is now completely explored. • The newly visited vertices which are not completely explored are put at the end

of a queue. • The first vertex of this queue is explored next. • Exploration continues until no unexplored vertices are left.

v1

For example: BFS(v1) of this graph yields v1,v2,v3,v4,v5,v6

v2 v3 v4

v5 v6

Page 39: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

38

Depth First Search (DFS)

• In this technique we start from a given vertex v and then mark it as visited.

• A vertex is said to be explored when all the vertices adjacent to it are

visited. • An vertex adjacent to v are put at the top of a stack next. • The top vertex of this stack is explored next. • Exploration continues until no unexplored vertices are left. • The search process can be described recursively.

v1

For example: DFS(v1) of this graph yields v1,v2,v5,v6,v3,v4

v2 v3 v4

v5 v6

Page 40: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

39

Assignments

3.3 Implement the BFS algorithm 3.4 Implement the DFS algorithm

BFS(v) { DFS(v)

u = v; {

visited[v] = true; visited[v] = true;

// visited is an array of vertices visited so far, // visited is an array of vertices

// all elements are 0 initially // visited so far, all elements are 0 initially

do { for all vertices w adjacent to v do

for all vertices w adjacent to u do { {

if (!visited[w]) { if (!visited[w])

add w to q; DFS(w);

// q is the queue of }

// unexplored vertices }

visited[w] = true;

}

}

if (q empty) return;

u = extract front element of q;

} while (true);

}

Page 41: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

40

Putting them all together

• Create a file named Graph.h in algo_lab/inc/algorithms directory. • Put the definition of struct edge, n (nr. of vertices) and infinity in that file • Declare the readGraph, getEdges, BFS & DFS functions there. • Create a file named Graph.c in algo_lab/src/algorithms directory. • Implement the readGraph, getEdges, BFS & DFS function there. • Add two menu items for BFS & DFS. • When you implement the menu callbacks for BFS & DFS, you must

read the graph from a file given by the user. Use the readGraph method to achieve this.

Page 42: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Heap and Priority Queue

WEEK 4

Page 43: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

42

Trees & Binary Trees

• A tree is a connected graph without any circuits (i.e. a minimally connected graph).

A tree

• A binary tree t is a finite (may be empty) set of vertices. • A non-empty binary tree has a root vertex. • The remaining vertices (if any) can be partitioned into two binary trees,

which are called the left and right sub-trees of t.

root

Left sub-tree right sub-

of root

tree of root

Page 44: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Properties of Binary Tree

• Level

– By definition root is at level 1

– Children of root are at level 2

– Their children are at level 3 and so on… • Height

level1 43

Height = 3 level2

level3

Full binary tree

– The height or depth of a binary tree is the number of levels in it

• A binary tree of height h (h ≥ 0) has at least h and at most

2h – 1 vertices in it. • A binary tree of height h that has exactly 2h – 1 vertices is

called a full binary tree. • If every non-leaf node in a binary tree has non-empty left

and right sub-trees, the tree is called a strictly binary tree. • A binary tree is called a complete binary tree, if all its

levels, except possibly the last have the maximum number

Strictly binary tree Complete binary tree

of possible vertices, and if all vertices at the last

Page 45: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

level appear as far left as possible.

Page 46: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

44

Heap

• A max (min) heap is a complete binary tree such that the root is greater (less) than its children.

12 3

10

8 10

8

5 4 15 14 12

Max Heap Min Heap

• A max (min) heap can be represented by an array, as shown:

3 (1)

10 8

1 2 3 4 5 6

(3)

(2)

3 10 8 15 14 12

15

12

14

(4) (6) Array representing the min heap

(5)

Min Heap

• Root is at index 1 of the array, left child of root is at index 2, right child of root is at index 3. In general, if index of an element is i, its left child is at 2 * i and right child is at 2 * i + 1

Page 47: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

45

Heapify

• Heapify is an important method for manipulating heaps. In our examples we have illustrated with min heaps, similar method can be employed for max heaps as well.

• The heapify method takes two inputs, an array a[] and an index i of the

array. It is assumed that the left and right sub-trees of the binary tree rooted at i are min-heaps, but a[i] may be greater than its children.

9 (1)

8 10 1 2 3 4 5 6

(3)

(2) 9 8 10 15 14 12

15 14 12

(4) (6)

The array a[ ]

(5)

e.g. heapify(a, 1) Notice that a[1] > a[2] But trees rooted at index 2 and 3 are min-heaps

• We find the min of a[i] and its left and right child. Then a[i] and a[min] are interchanged.

8 (1)

10

1 2 3 4 5 6

9

(3) 8 9 10 15 14 12

(2)

15 14 12

(4) (6)

(5)

Page 48: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Elements a[1] and a[2] have been interchanged

Page 49: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

46

Heapify

• We now recursively apply the same process to the sub-tree in which the interchange took place.

8 (1)

10 1 2 3 4 5 6

9

(3) 8 9 10 15 14 12

(2)

15 14 12

(4) (6)

(5)

Now recursively call heapify(a, 2) But since the sub-tree at index 2 is already a min-heap no further change is necessary

• Thus, we can re-arrange the elements of array a[] by the heapify(a[], i) method, such that the sub-tree rooted at index i becomes a min-heap.

8

(1)

9 10

(3)

(2)

15 14 12

(4) (6)

(5)

The resultant min-heap rooted at 1

Page 50: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

47

Priority Queue

• A priority queue is a data structure for maintaining a set S of elements, each with an associated value called a key. A min-priority queue supports the following operations.

– insert(x) // inserts element x in the priority queue

– extractMin() // removes & returns the element with smallest key

– decreaseKey(x, k) // decreases the value of element x’s key to k

– findPQ() // search for the element in the priority queue

• A priority queue can be implemented by a heap.

Page 51: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

48

Implementing a Priority Queue of structures

• Say, we want to create a Priority Queue of nodes, where each node is defined as a structure, containing an index and a key value.

typedef struct Node {

int index;

int key;

} node;

• We define the Priority Queue as a structure as well, containing an array (heap) of nodes and a size attribute.

typedef struct priorityqueue {

node* heap[50];

int size;

} PriorityQueue;

Page 52: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

49

Priority Queue: extractMin Operation

• The extractMin() operation removes the first element of the heap, puts the last (nth) element in the heap in the first position, then calls heapify to re-create a heap of n – 1 elements.

heapify(node* a[], int i, int n) { extractMin(PriorityQueue* pq) {

int l = 2 * i, r = 2 * i + 1, min = i; if (pq→size == 0) return 0;

if (l ≤ n AND a[l]→key < a[min]→key) node* n = pq→heap[1];

min = l; pq→heap[1] = pq→heap[pq→size];

if (r ≤ n AND a[r]→key < a[min]→key) pq→size--;

min = r; heapify(pq→heap, 1, pq→size);

if (min ≠ i) { return n;

exchange(a[i], a[min]); }

heapify(a, min, n);

}

}

Page 53: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

50

Priority Queue: decreaseKey operation

• The decreaseKey() operation decreases the key of the element i to k. The priority-queue element whose key is to be increased is identified by an index i into the array. The procedure first updates the key of element heap[i] to its new value. Because decreasing the key of heap[i] may violate the min-heap property, the procedure then traverses a path from this node toward the root to find a proper place for the newly decreased key.

decreaseKey(PriorityQueue* pq, int i, int val) {

pq→heap[i]→key = val;

while (i > 1 AND pq→heap[parent(i)]→key > pq→heap[i]→key)

{ exchange(pq→heap[i], pq→heap[parent(i)]);

i = parent(i);

}

}

Page 54: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Priority Queue: insert & findPQ Operations

51

• The insert operation takes as an input the key i of the new element to be inserted into the min-heap. The procedure first expands the min-heap by adding to the tree a new leaf. Then it calls decreaseKey() to set the key of this new node to its correct value and maintain the min-heap property.

insert(PriorityQueue* pq, int i, int val) {

pq→size++;

node* n = (node*)malloc(sizeof(node));

n→key = i;

pq→heap[pq→size] = n;

decreaseKey(pq, pq→size, val);

}

• Since we are implementing the heap as an array, the findPQ operation can be implemented as linear search in the array.

int findPQ(PriorityQueue* pq, int ind) { // find the element whose index is ind

for (i = 1 to pq→size)

if (pq→heap[i]→index == ind) return i; // found

return 0; // not found

Page 55: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

}

Page 56: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

52

4.1 Assignments • Implement a PrioirityQueue.h file in algo_lab/inc/algorithms

directory. Put the definitions of struct node, struct PriorityQueue and functions extractMin(), insert(), decreaseKey(), findPQ() there.

• Implement a PriorityQueue.c file in algo_lab/src/algorithms directory. Put the implementations of extractMin(), heapify(), insert(), decreaseKey(), findPQ() there.

• Implement a new menu item for demonstrating Priority Queue.

• Test your implementation by accepting a set of elements from the user and then printing their sorted order by first constructing a priority queue with those elements and then repeatedly calling the extractMin() operation.

Page 57: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Disjoint Sets & Job Sequencing

WEEK 5

Page 58: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

54

Disjoint Sets

• Say, we have disjoint sets of numbers 1, 2, 3, …, n • i.e. if Si & Sj (i ≠ j) are two disjoint sets, then there is no element that is

in both Si & Sj

• For example, say there are three sets S1 = {1, 3, 6, 8}, S2 = {2, 5, 7}, S3 = {4, 9}

• We can represent the sets as trees, with the exception that instead of

parent nodes pointing to children nodes, the children nodes point to the parent node.

1 2 4

3 6 8 5 7 9

S1

S2 S3

Page 59: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

55

Disjoint Set Operations

• Union

– If Si and Sj be two disjoint sets then their union Si U Sj

are all elements x such that x is in Si or Sj. So S1 U S2 in our example = {1, 3, 6, 8, 2, 5, 7}.

• Find

– Given an element x, find(x) operation tells us to which

set x belongs. So 3 is in S1 and 9 is in S3

Page 60: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

56

Union & Find

• To obtain union of Si and Sj we simply make one of the trees a sub-tree of the other.

• Thus to obtain union of two disjoint sets we have to set the

parent field of one of the roots to the other root.

1

3 6 8 2

5 7

• For simplicity let us ignore the set names and represent the sets by the roots of the trees representing them.

• The operation Find(i) now becomes determining the root of

tree containing element i.

Page 61: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

57

Array representation of disjoint sets

• Since the set elements are numbered 1 … n, we can represent the tree nodes using an array p[1 … n].

• The ith element of this array represents the tree nodes that

contain element i. • This array element gives the parent of the corresponding

node. • For root nodes the value of parent is set to -1. • Thus, we can represent the sets S1 = {1, 3, 6, 8}, S2 = {2, 5, 7}, S3

= {4, 9} by the following array:

i 1 2 3 4 5 6 7 8 9

p -1 -1 1 -1 2 1 2 1 4

Page 62: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

58

Algorithms for union & find

Union (i, j) { // union of two trees with roots at i & j

p[i] = j;

}

Find(i) {

while (p[i] ≥ 0) { i = p[i];

} return i;

}

Page 63: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

59

Degenerate Tree

• Say we have n sets, each having one element {1}, {2}, …, {n}, i.e. a forest of n one-element trees.

• Now, if we perform the following sequence of union

operations:

– Union(1, 2), Union(2, 3), …, Union(n – 1, n)

• We will get a degenerate tree as shown in the picture.

• Since the union algorithm runs in constant time, the n – 1 unions will be processed in O(n) time.

• But now, if we perform the following sequence of find operations on the degenerate tree:

– Find(1), Find(2), …, Find(n)

• Time needed to perform a find at level i of the tree would be O(i) n

• Hence the total time needed for all the finds is: i O(n2 ) i1

Page 64: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

60

Weighting rule for union

• We can improve the performance of our Union and Find algorithms by avoiding the creation of degenerate trees. To accomplish this we will use the weighting rule for Union(i, j)

• Weighting rule for Union(i, j)

– If the number of nodes in the tree with root i is less than the number of nodes in the tree with root j, then make j the parent of i, else make i the parent of j.

• When we use the weighting rule of union to perform the set of

unions given before, we obtain the following:

… … … Union(1, n)

initial Union(1, 2)

Union(1, 3)

Page 65: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

61

Implementation of weighting rule

• To implement the weighting the weighting rule we need to know how many nodes are present in a tree.

• To achieve this we maintain a count field in the root of every tree. • If r is a root node the count(r) equals number of nodes in that tree. • Since all nodes other than roots have a positive number in the p

field, we maintain the count in the p fields of the root as a negative number.

• Thus, we can represent the sets S1 = {1, 3, 6, 8}, S2 = {2, 5, 7}, S3 = {4, 9} by the following array:

i 1 2 3 4 5 6 7 8 9

p -4 -3 1 -2 2 1 2 1 4

Page 66: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Path Compression

• Further improvements are possible by modifying the find(e) procedure, so as to compress the path from element e to the root.

• For example, let us consider the performance of

the following 4 finds in the given tree: – Find(4), Find(4), Find(4), Find(4)

• Each Find(4) requires going up three parent link

fields, resulting in 12 moves for the 4 finds. • During the first Find(4) nodes 5, 2 are determined

to be in the 4 to the root 1. • Now if we change the parent fields of 4 and 5 to 1

(2 already has 1 as parent), we get the resulting tree:

• Each of the remaining finds now requires going up

only 1 parent link field. • The total cost is now only 7 moves.

62

1

3 6 8

2

5 7

4

1

5

3 6 8

4 2

7

Page 67: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

63

Weighted Union & Path Compression Algorithms

weightedUnion(u, v) {

if (p[u] > p[v]) { p[v] += p[u]; p[u] = v;

} else { p[u] += p[v]; p[v] = u; }

}

compressedFind(v) {

if (p[v] < 0) return v;

p[v] = compressedFind(p[v]);

return p[v];

}

Page 68: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

64

Assignment

5.1 Implement the DisjointSet.C file in algo_lab/src/algorithms directory with the following methods.

initDisjointSet(int n); // initialize the array p with every element as -1

void weightedUnion(int u, int v); // weighted union of two disjoint sets rooted at u & v

int compressedFind(int v); // perform compressedFind for v

• Add the declaration of these methods in algo_lab/inc/algorithms/DisjointSet.h file

• Test your implementation to verify that it works correctly.

Page 69: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

65

Application: Job Sequencing with Deadlines

• We are given a set of n jobs

• Associated with each job is an integer deadline di > 0 and a profit pi > 0 • For any job the profit is earned if and only if it is completed within

deadline • Basic Assumptions:

1. Only one job can be processed at a time

2. Once the job gets started it must be allowed to perform till completed

3. No job can miss the deadline, i.e. it must complete within the deadline

4. To complete each job it takes one unit of time • Our problem is to maximize the profit such that maximum jobs are

completed within deadline. • We have to sequence these jobs in such a way to gain maximum profit.

Page 70: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

66

Job Sequencing Example

• Let n (number of jobs) = 5, p (array of profits) = {10, 5, 15, 1, 20} and d (array of deadlines) = {1, 3, 2, 3, 2}

• First thing to note is that the maximum value of deadline is 3, since each

job needs one unit of time, only 3 jobs can be performed. Question is doing which 3 can earn us the greatest profit?

• We will make a greedy choice and try to schedule the job with the highest

profit first, i.e. j5. • Next we must decide when to do j5. We have 3 timeslots available with us,

1, 2 & 3. In which timeslot should we schedule j5? • Here our policy would be to defer the job to be scheduled as much as

possible. Note that the deadline for j5 is 2, hence we can do j5 latest by timeslot 2. We choose this timeslot to do j5.

• Then we will consider the job with the 2nd greatest profit, i.e. j3. and schedule it in the latest available timeslot, which is timeslot 1.

• We continue in this manner until all the timeslots are exhausted.

Page 71: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

67

Job Sequencing Example

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2}

• The following table illustrates the sequence of steps executed by our algorithm, for the given example.

Schedule Assigned Slots Job Considered Action Profit

{} none 5 Assign to slot 2 0

{5} 2 3 Assign to slot 1 20

{5, 3} 1, 2 1 Can’t schedule, reject 35

{5, 3} 1, 2 2 Assign to slot 3 35

{5, 3, 2} 1, 2, 3 4 reject 40

• The optimum schedule is {5, 3, 2} and the optimum profit is 40.

Page 72: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

68

Job Sequencing Example

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2}

• To implement this algorithm we must be able to identify the latest available slot for a given deadline.

• To achieve this we partition the jobs in sets of their deadlines. • Two jobs are in the same set if the latest available slot for both of them

is the same. • For example, initially we have 3 sets (remember the max deadline is 3),

because all the slots are free.

1 2 3

• This is another way of saying that a job with deadline 1 can be done latest in time slot 1, a job with deadline 2 can be done latest by time slot 2 and a job with deadline 3 can be done latest by time slot 3.

• This is represented by an array f[] = {0, 1, 2, 3}. Again, f[1] = 1 is to say

that job 1 can be done latest by time slot 1, and so on.

Page 73: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

69

Job Sequencing Example

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2}

• At first we schedule j5 in time slot 2, so time slot 2 is no longer available. Now if we get another job with deadline 2, the latest available time slot for that job is 1. But if we are to get a job with deadline 1, the latest available time slot for that job is tie slot 1 as well. So the latest available time slot for a job of deadline 2 and deadline 1 is now the same, i.e. 1.

• We represent this by putting 2 & 1 in the same set. To put them in the same

set we perform a weightedUnion of sets {2} & {1}. 1

3

this means that a job with deadline 2 and a job with

deadline 1 can be done latest by the same time slot

2

• Since now, a job with deadline 2 can be done latest by time slot 1, we set f[2] = 1, hence f[] = {0, 1, 1, 3}

• Next we consider j3, which has a deadline 2. We want to know what is the latest available time slot for this job?

Page 74: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Job Sequencing Example 1 70

3

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2} 2

• To find out which is the latest available time slot for j3 which has deadline 2, we first perform a compressedFind of the element 2 in the disjoint set. This gives us 1, since 1 is the root of the tree in which 2 belongs. Now we check the value of f[1], which is again 1. So, we conclude that j3 can be performed latest by time slot 1.

• But the latest available time slot for any job with deadline 1 is now 0, so

we set f[1] = 0. So the array f now looks like {0, 0, 1, 3}

• The next job under our consideration (by greedy choice) would be j1. But as we had seen it can’t be scheduled. But how do we take this decision?

• To decide whether a job can be scheduled, we introduce a fictitious time

slot 0. 0

• If the latest available time slot for a job is 0, then we conclude that it can’t be scheduled.

Page 75: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Job Sequencing Example 1 71

03

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2} 2

• Now, to find out which is the latest available time slot for j1 which has deadline 1, we first perform a compressedFind of the element 1 in the disjoint set. This gives us 1. Now we check the value of f[1], which is 0. Which means that j1 can be performed latest by time slot 0. In other words, we reject j1 as it can’t be scheduled.

• The next job under our consideration (by greedy choice) would be j2, which has a deadline of 3.

• To find out the latest available time slot for j2, we perform a

compressedFind of the element 3 in the disjoint set. This gives us 3. Now we check the value of f[3], which is 3. Which means that j2 can be performed latest by time slot 3. So we schedule it in this time slot.

• Which means that now that latest available time slot for jobs with deadline

3, 2 and 1 are now the same, i.e. 0. As before we represent this by putting them in the same set by performing a weightedUnion(1, 3)

Page 76: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

72

Job Sequencing Example

n = 5, p = {10, 5, 15, 1, 20}, d = {1, 3, 2, 3, 2}

• So our disjoint set looks like the following now.

1

0

3 2

• Since, no other time slot (apart from 0) is available, no more jobs can be scheduled.

• The optimal schedule is thus {5, 3, 2} giving us an optimal profit of 20 + 15

+ 5 = 40.

Page 77: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

73

Representing a Job as a structure

• We will represent each job in our algorithm as a C structure, containing three fields, an id (to uniquely identify a job), a deadline and a profit value.

typedef struct Job { int id;

int profit;

int deadline;

} job;

• Suppose we are given an array of struct Job, our greedy strategy dictates that we pick jobs in order of profits, i.e. the highest profit job first, the 2nd highest profit job next and so on.

• So, it would require us to sort the array of jobs in decreasing order of profits

to achieve our goal. • Question is: how do we sort an array of structures in C?

Page 78: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

The qsort function to rescue

74

• We will use the qsort (quick sort) function of C to sort an array of structures. • The qsort function is defined in stdlib.h, so firstly make sure that you #include

<stdlib.h> in your code. • The qsort function takes four parameters: qsort(base, n, size, cmpFunc); • Here base is the base pointer to the array to be sorted, n is the number of elements in

the array, size is the size of each element in the array and cmpFunc is the pointer to the function which compares the elements in the array.

• We would of course need to provide the implementation of cmpFunc. • The cmpFunc takes two constant void pointers to two elements in the array, and

returns an integer which is positive if element1 > element2, negative if element1 < element2 and 0 if element1 == element2. For example, our job comparator looks like:

int jobCmp(const void* arg1, const void* arg2) {

job* j1 = (job*)arg1; job* j2 = (job*)arg2;

// j1, j2 are pointers to two jobs

return (j2->profit - j1->profit); // +ve if j2→profit is more, -ve if j2→profit is less, 0 if equal

Page 79: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

}

Page 80: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Assignment 75

5.2 Implement the greedy job scheduling with deadlines algorithm

JobSchedule(job jobs[]) { // schedule the jobs optimally in j[1 … k]

qsort(jobs, n, sizeof(job), jobCmp); // sort jobs in decreasing order of profits

b = min(n, maxDeadline); // number of jobs that can be performed

initDisjointSet(b);

k = 0;

for (i = 0 to b) f[i] = i; // mark all time slots available initially

for (i = 0 to n - 1) { // consider jobs according to greedy choice

q = compressedFind(min(n, jobs[i].deadline)); // latest available time slot for job i

if (f[q] ≠ 0) { // proceed only if this job can be scheduled

j[k++] = jobs[i].id; // schedule job i

m = compressedFind(f[q] - 1);

weightedUnion(m, q); // jobs with deadline m, q now belong to the same set

f[q] = f[m]; // latest available time slots for deadline m, q are same

}

} }

Page 81: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Thank you!!!

“If debugging is the process of removing bugs, then programming must be the process of putting them in.”

- Dijkstra

Page 82: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your
Page 83: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Design & Analysis of Algorithms

Laboratory Instructions & Assignments By: Prof. Sourav Saha Prof. Pinaki karmakar

Page 84: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your
Page 85: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Minimum Spanning Tree Algorithms

WEEK 6

Page 86: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

3

Minimum Spanning Tree

A tree T is said to be a spanning tree of a connected graph G if T is a sub-graph of G and T contains all vertices of G.

The weight of a spanning tree T of G is defined as the sum of the weights of all the branches of T.

A spanning tree with the smallest weight in a weighted graph is called a

minimal spanning tree.

Given a weighted graph G, we have to find a minimal spanning tree of the graph.

v2

5 1

v1 2 v4

4

3

v3

Page 87: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Finding The Minimal Spanning

4

Tree

Greedy

Strategy

Let A be a sub-set of the minimal spanning tree

At each step determine an edge (u, v) such that, if we add (u, v) to A, A remains a subset of the minimal spanning tree.

The edge (u, v) is called a safe edge

for A.

Page 88: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

5

Kruskal’s Algorithm

8

7 v2 v4

v1 2

5 3

v3

List all the edges of the graph G in order of non-decreasing weight.

(v2, v3), (v3, v4), (v1, v3), (v1, v2), (v2, v4)

Select a smallest edge from G

(v2, v3)

From the remaining edges select the smallest edge which doesn’t make a circuit with the previously selected edges.

(v2, v3), (v3, v4)

4. Continue until (n – 1) edges have been selected

v2 v4

(v2, v3), (v3, v4), (v1, v3) v1

2

5 3

v3

Page 89: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

6

Strategy

• Read the input graph from a file using the readGraph method (refer to Assignment 3.1)

• Get an array of edges of the graph using the getEdges method (refer to

Assignment 3.2) • Sort the edges of the graph using the qsort method (refer to Assignment

5.2) • The function to compare edges may be implemented as:

int edgeCmp(const void* a1, const void* a2) {

edge* e1 = (edge*)a1;

edge* e2 = (edge*)a2;

return (e1->cost - e2->cost);

}

To check whether a circuit is formed with the previously selected edges we will use the compressedFind and weightedUnion operation of Disjoint Sets (refer to Assignment 5.1)

Page 90: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

7

Assignments

Implement Kruskal’s Algorithm:

void kruskal(G)

initDisjointSet(n);

k = getEdges(G, edges);

qsort(edges, k, sizeof(edge), edgeCmp)

for (i = 0 to k - 1)

u = edges[i].u

v = edges[i].v

if (compressedFind(u) ≠ compressedFind(v))

weightedUnion(u, v)

print edge (u, v) in MST

if (++nodes == n - 1) break

Page 91: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

8

Prim’s Algorithm

8

7 v2 v4

v1 2

5 3

v3

0 7 5

7 0 2 8

5 2 0 3

8 3 0

Start with vertex v1 and connect to the vertex which has the smallest entry in row

1, say vk.

(v1, v3)

Now consider (v1, vk) as one sub-graph and connect this sub-graph to a vertex

other than v1 and vk that has the smallest entry among all entries in rows 1 and k,

say vj.

(v1, v3), (v3, v2)

3. Now regard the tree with vertices v1, vk and vj as one sub-graph and continue this

process until n vertices have been connected by n – 1 edges.

(v1, v3), (v3, v2), (v3, v4) v2 v4

v1 2

5 3

Page 92: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

v3

Page 93: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

9

Strategy

• Read the input graph from a file using the readGraph method (refer to Assignment 3.1). Pass the weighted adjacency matrix G and a source vertex s to the Prim function.

• Initialize an array d[] of size n using the init method, set d[s] to 0 and all other elements

of d[] to ∞. Keep the init method in a separate file Common.h

init(G, s)

foreach (vertex v of G)

d[v] = ∞

p[v] = -1

d[s] = 0

Initialize a priority queue with the d[] array (insert each element of d in the priority queue)

At every step get a vertex u, using the extractMin method of the priority queue

For each vertex v adjacent to u, if v exists in the priority queue, let i be its index in the heap, then set p[v] to u, d[v] to G[u][v] and decrease the key of the ith element of priority queue to d[v]

For each element i of the array p[1 … n - 1], the pair (p[i], i) gives an edge in the MST

Page 94: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

10

Assignments

Implement Prim’s Algorithm:

void prim(G,

s) init(G, s);

PriorityQueue* pq = initPQ(d, n);

while ((e = extractMin(pq)))

u = e→index

for (v = 0 to n - 1)

if ((G[u][v]) AND (G[u][v] ≠ ∞))

i = findPQ(pq, v)

if (i AND G[u][v] <

d[v]) p[v] = u

d[v] = G[u][v]

decreaseKey(pq, i, d[v])

Page 95: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Knapsack & MaxMin Algorithms

WEEK 7

Page 96: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

12

Knapsack Problem

A Thief enters a store in the night, with a knapsack in his hand.

The knapsack can carry only a certain amount of weight, say W at most.

The store has n items, each having a value V and weight W.

The thief has to select items, such that he fills his knapsack with items, giving him the maximum value.

There are two variations of this problem.

In the 0/1 knapsack problem the thief has to either take the entire item or

leave it altogether.

In the fraction knapsack problem the thief is allowed to take fraction of items.

For example, if the store contained gold biscuits it would constitute a 0/1 knapsack problem. Whereas if the store contained gold dust, it would constitute a fraction knapsack problem, since the thief can take a portion of the gold dust.

Page 97: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

13

Example

• Let us suppose the store has three items as shown below:

Item Value (V) Weight (W) V/W

1 60 10 6

2 100 20 5

3 120 30 4

Let the Knapsack capacity be 50.

The thief would like to make a greedy choice, hence he will pick up items with higher V/W values.

Page 98: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

14

Example: 0/1 Knapsack Problem

Let us assume that it is a 0/1 Knapsack Problem, i.e. the thief has to either take the whole item or leave it.

By making a greedy choice the thief would pick up items 1 & 2 first, thereby filling the knapsack by W = 30 and earning V = 160

He can’t take the item 3 anymore since his knapsack can only take 20 units of weight, whereas item 3 weighs 30.

But as we can see, if the thief picked up items 2 & 3 he would have earned V = 220.

Thus greedy choice did not lead to an optimal solution

Page 99: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Example: Fraction Knapsack

15

Problem

• Let us assume that it is a Fraction Knapsack Problem, i.e. the thief can take a part of an item.

• By making a greedy choice the thief would pick up items 1 & 2 first,

thereby filling the knapsack by W = 30 and earning V = 160 • He will now take 20 units of weight of item 3, thereby gaining another

80 units of money. • His total profit is 160 + 80 = 240 • Thus greedy choice leads to an optimal solution for a fraction

knapsack problem.

Page 100: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

16

Strategy

Implement each item as a structure.

typedef struct item

{

int weight; int value;

}item;

• Sort the items in decreasing order of value/weight by the qsort method. The item comparator method may be implemented as:

int compare(const void *x, const void *y)

{

item *i1 = (item *)x, *i2 = (item *)y;

double ratio1 = (*i1).value*1.0 / (*i1).weight;

double ratio2 = (*i2).value*1.0 / (*i2).weight;

return ratio2 – ratio1;

}

• Finally iterate over items and select them by greedy choice.

Page 101: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

17

Assignment

7.1 Implement the Knapsack algorithm

Knapsack(item items[], int n, int maxWeight) qsort(items, n, sizeof(item), compare) value = 0.0

presentWeight = 0 for(i = 0 to n – 1)

if (presentWeight + items[i].weight < maxWeight) presentWeight += items[i].weight

value += items[i].value

else

remaining = maxWeight - presentWeight

value += items[i].value * remaining * 1.0 / items[i].weight break

return value

Page 102: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

18

MaxMin Algorithm

• Let us consider the problem of finding the maximum and minimum of an array a[1 … n] of n integers.

• We would formulate a divide and conquer algorithm to solve this as

follows: • If the array contains one element then max and min are both the same

(which is the only element in the array) • If the array contains two elements the greater of them is max and the

lesser of them is min • If the array contains more than two elements divide it into two parts P1,

P2 along the mid-point, and then find the max and min of the two parts recursively. Then max = larger(max(P1), max(P2) and min = smaller(min(P1), min(P2))

Page 103: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

19

Assignment

7.2 Implement the MaxMin Algorithm

maxMin(i, j, max, min)

if (i == j) max = min = a[i] else if (i == j – 1)

if (a[i} > a[j])

max = a[i] min = a[j]

else

max = a[j] min = a[i]

else

mid = (i + j) / 2 maxMin(i, mid, max, min)

maxMin(mid + 1, j, max1, min1) if (max < max1) max = max1 if (min > min1) min = min1

Page 104: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Single Source Shortest Path

WEEK 8

Page 105: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

21

Shortest Path Problem

8 0 7 5

7v2 v4

0 2 8

v1 2 D

5 3

0 3

v3

0

• A simple weighted directed graph G can be represented by an n x n matrix D = [dij] where:

– dij = weight of the directed edge from i o j

– = 0, if i = j

– = ∞, if there is no edge between i and j

• We have to find out the shortest path from any given vertex to all other vertices

Page 106: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

22

Dijkstra’s Algorithm

• Begin

1. Assign a permanent label 0 to the start vertex and a temporary label ∞ to all other vertices

2. Update label of each vertex j with temporary label using the following

rule:

Labelj = min[Labelj, Labeli + dij]

Where i is the latest vertex permanently labeled and dij is the direct distance between i and j.

0 Choose the smallest value among all the temporary labels as the new permanent label. In case of a tie select any one of the candidates.

1 Repeat steps 2 and 3 until all the vertices are permanently labeled

• End

Page 107: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

23

Dijkstra’s Algorithm

8

7 v2 v4

v1 2

5 3

v3

v1 v2 v3 v4

0 ∞ ∞ ∞

0 7 5 ∞

0 7 5 8

0 7 5 8

Page 108: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

24

Strategy

• Read the input graph from a file using the readGraph method (refer to Assignment 3.1). Pass the weighted adjacency matrix G and a source vertex s to the dijkstra function.

• Initialize an array d[] of size n using the init method, set d[s] to 0 and all

other elements of d[] to ∞. Refer to Assignment 6.2 • Initialize a priority queue with the d[] array (insert each element of d in the

priority queue) • At every step get a vertex u, using the extractMin method of the priority

queue • For each vertex v adjacent to u, call relax(u, v, G) and decrease the key of v

in the priority queue to d[v] • The relax method can be implemented as follows (put it in Common.h)

relax(u, v, G)

if (d[u] > d[v] + G[u][v])

d[u] = d[v] + G[u][v] p[v] = u

Page 109: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

25

Assignment

• Implement Dijkstra’s Algorithm

dijkstra(int G[][n], int s) init(G, s)

PriorityQueue* pq = initPQ(d, n) while ((e = extractMin(pq)))

u = e->index

for (v = 0 to n - 1)

if ((G[u][v]) AND (G[u][v] ≠ ∞)) relax(u, v, G)

decreaseKey(pq, findPQ(pq, v), d[v])

Page 110: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

26

Bellman-Ford Algorithm

• The Bellman-Ford algorithm solves the single source shortest path problem for graphs, in which the edge weights may be negative

• The Bellman-Ford algorithm indicates whether or not there is a

negative weight cycle, reachable from the source, in the graph • If there is such a cycle the algorithm indicates that no such solution

exists by returning a Boolean false • If there is however no such cycle the algorithm produces the shortest

paths from the source vertex to every other vertex and their weights

Page 111: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

27

Assignment

8.2Implement Bellman-FordAlgorithm

bellmanFord(int G[][n], int s) init(G, s)

for (i = 1 to n - 1)

for (u = 0 to n - 1)

for (v = 0 to n - 1)

if ((G[u][v]) AND (G[u][v] ≠ ∞)) relax(u, v, G)

for (u = 0 to n - 1)

for (v = 0 to n - 1)

if ((G[u][v]) AND (G[u][v] ≠ ∞))

if (d[v] > d[u] + G[u][v]) return 0

return 1

Page 112: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

All Pairs of Shortest Paths, N-Queens

WEEK 9

Page 113: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

29

All pairs of shortest paths

• Given a vertex of a graph, Dijkstra’s algorithm enables us to find the shortest path from that vertex to all other vertices

• The next problem is to find out the shortest path between any given

pair of vertices of a graph • The restriction is that G have no cycles with negative length • If we allow G to contain cycles with negative length then the shortest

path between any two vertices on this cycle is -∞ • The all pairs of shortest path problem is to determine a matrix A such

that A(i, j) is the length of the shortest path from i to j.

Page 114: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

30

All pairs of shortest paths

• We assume all the vertices of the graph are numbered from 1 to n • Let Ak(i, j) be the length of the shortest path from i to j going through no

intermediate vertex greater than k • Then there are two possibilities…

The path from i to j goes through k: In which case we can split the path in two parts, one from i to k and the other from k to j. Note that neither of these two paths can go through any intermediate vertex greater than

k – 1. Length of such a path is: Ak-1(i, k) + Ak-1(k, j) The path from i to j does not go through k: Which means that this path

goes through no intermediate vertex greater than k-1. Its length would

be: Ak-1(i, j)

• Clearly Ak(i, j) is the minimum of these two choices

• Hence Ak(i, j) = min{ Ak-1(i, j) , Ak-1(i, k) + Ak-1(k, j) }

Page 115: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

31

Assignment

9.1 Implement the all pairs of shortest paths algorithm

allPairs(int a[][n]) for (k = 0 to n - 1)

for (i = 0 to n - 1)

for (j = 0 to n - 1)

a[i][j] = min(a[i][j], a[i][k] + a[k][j]);

Page 116: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

32

The 8 Queens Problem

We have an 8x8 chessboard, our job is to place eight queens on the chessboard, so that no two of them can attack. That is, no two of them are in the same row, column or diagonal

Q

Q

Q

Q

Q

Q

Q

Q

Page 117: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

33

The n Queens Problem

The generalized version of the 8 Queens problem is the n Queens problem, where n is a positive integer. Let us illustrate a backtracking approach to this problem with a 4 Queens example.

Q1

Step1: Place Q1 on Col 1

Q1

X X Q2

Step2: Place Q2

Q1

X X Q2

X X X X

No legal place for Q3

Page 118: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

34

The n Queens Problem

Q1 Q1

X X X Q2 X X X Q2

X Q3

Q1

X X X Q2

X Q3

X X X X

Backtrack and alter Q2 Place Q3 No legal place for Q4

Q1

Q1

X X X Q2

Q1

X X X Q2

Q3

X X Q4

Page 119: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Backtrack and alter Q1 Place Q2 Place Q3 and then Q4

Page 120: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

35

The n Queens Problem

Let (x1, x2, …, xn) represent a solution in which xi is the column of the ith row, where

the ith queen has been placed. The xis will all be distinct, since no two queens can be in the same column.

Now, how to check that they are not in the same diagonal?

Q

Q

Q

Q

Q

Q

Q

Q

Page 121: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

36

The n Queens Problem

Let the chessboard square be represented by the 2D array a[1…8, 1…8].

Every element on the same diagonal that runs from top-left to right-bottom has the same (row – column) value.

For example, a Queen at a[4,2] has attacking Queens, diagonal to it at a[3,1], a[5,3], a[6,4] … (up-left to low–right).

Q

Q

Q

Q

Q

Q

Q

Q

Page 122: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

37

The n Queens Problem

Also all elements on the same diagonal from top-left to bottom-right have the same (row + column) value.

If the Queens are placed at (i,j) and (k,l) cells, then they are in the same diagonal only if

i – j = k – l or i + j = k + l i.e. abs(j – l) = abs(i – k)

Q

Q

Q

Q

Q

Q

Q

Q

Page 123: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

38

Assignment

9.2 Implement the n-queens algorithm

place(k, i)

for (j = 1 to k - 1)

if ((x[j] == i) || (abs(x[j] - i) == abs(j - k))) return 0;

return 1;

nQueens(k)

for (i = 1 to n)

if (place(k, i)) x[k] = i;

if (k == n) displayChessBoard(); else nQueens(k + 1);

Page 124: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Graph Coloring, Hamiltonian Cycles

WEEK 10

Page 125: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

40

Graph Coloring Problem

• Painting all the vertices of a graph with colors such that no two adjacent vertices have the same color is called the proper coloring of a graph.

• A graph in which every vertex has been assigned a color according to

proper coloring is called a properly colored graph. • A graph G that requires k different colors for its proper coloring,

and no less, is called a k-chromatic graph. The number k is called the chromatic number of G.

Page 126: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

41

Graph Coloring Problem

• Let m be a given positive integer. In our example, say m = 3. • We want to find whether the nodes of G can be colored in such a way

that no two adjacent nodes have the same color, yet only m colors are used.

• We design a backtracking algorithm such that given the adjacency

matrix of a graph G and a positive integer n, we can find all possible ways to properly color the graph.

Page 127: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

42

Graph Coloring Problem: How it works

• Let Red

be color 1

• Let Green be color 2

• Let Blue

be color 3

• Let us examine how the backtracking algorithm for coloring works:

b

a

e

c d

Page 128: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

43

Graph Coloring Problem

b b

a

e

a

e

c

d

c

d

b b

a

e

a

e

c

d

c

d

Page 129: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

44

Assignment

10.1 Implement the Graph Coloring Algorithm

void nextColor(k, G) do {

x[k] = (x[k] + 1) % (m + 1); if (x[k] == 0) return; int j; for (j = 0; j < n; j++)

if ((G[j][k] ≠ 0) AND (x[k] == x[j])) break;

if (j == n) return;

} while (true);

void mColoring(k, G) do {

nextColor(k, G); if (x[k] == 0) return;

if (k == n - 1) display(); else mColoring(k + 1, G);

} while (true);

Page 130: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

45

Hamiltonian Cycles

• Let G(V, E) be a connected graph with n vertices. A Hamiltonian cycle is a round trip path in G that visits every vertex once and returns to the starting position.

• The graph G1 below has Hamiltonian cycles.

0 1 2 3

7 6 5 4

• Whereas G2 has no Hamiltonian cycles.

1

0

2

4 3

• We want to find all the Hamiltonian cycles in a graph

Page 131: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Hamiltonian Cycles

• The following figure illustrates the backtracking approach for a

possible solution

a

b

a

b

c f

c

d e d

e

Given graph

e d f

Dead end Dead end

46

f

e

c

d

f Part of the solution tree

a

Dead end

Page 132: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Solution

Page 133: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

47

Assignment

10.2 Implement the Hamiltonian Cycles Algorithm

nextVertex(k, G) do {

x[k] = (x[k] + 1) % (n + 1); if (x[k] == 0) return;

if (G[x[k - 1] - 1][x[k] - 1] ≠ 0) {

for (j = 1 to k - 1)

if (x[k] == x[j]) break; if (j == k)

if ((k < n) OR ((k == n) AND G[x[n] - 1][x[1] - 1]))

return;

} while (true);

hamilton(k, G) do {

nextVertex(k, G); if (x[k] == 0) return;

if (k == n) displayCycle(); else hamilton(k + 1, G);

} while (true);

Page 134: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your

Thank you!!!

“If debugging is the process of removing bugs, then programming must be the process of putting them in.”

- Dijkstra

Page 135: Design & Analysis of Algorithms - WordPress.com How to compile your code To compile and build the executable type ./build in the algo_lab directory. ./build This will compile your