Professional Documents
Culture Documents
ORM Practicals-2
ORM Practicals-2
Aim: Write a program for implementing simplex method(two phase and dual simplex method.)
Theory:
Two Phase Simplex Method: In this method, the problem is solved in two phases as given
below.
First Phase:
(a) All the terms on R.H.S. should be non-negative. If some are -ve then they must be made +ve
as explained earlier.
(b) Express constraints in standard form.
(c) Add artificial variables in equality constraints or (>) type constraints.
(d) Form a new objective function W which consisted of the sum of all the artificial variables
W = A1 + A2 + …………………… + Am
Function (W) is known as infeasibility form.
(e) Function W is to be minimized subject to constraints of original problem and the optimum
basic feasible solution is obtained.
Any of the following three cases may arise:
(i) Min. W > 0 and at least one artificial variable appears in column “Basic variables” at Positive
level. In such case, no feasible solution exists for the original L.P.P. and the procedure is
stopped.
(ii) Min. W = 0 and at least one artificial variable appears in column “Basic Variables” at zero
level. In such a case, the optimum basic feasible solution to the infeasibility form may or may
not be a basic feasible solution to the given (original) L.P.P. To obtain a basic feasible solution,
we continue phase I and try to drive all artificial variables out of the basis and then proceed to
phase II.
(iii) Min. W=0 and no artificial variable appears in the column “Basic variables” current
solution’. In such a case a basic feasible solution to the original L.P.P. has been found. Proceed
to phase II.
Second Phase:
Use he optimum basic feasible solution of phase I as a starting solution for the original L.P.P.
Using simplex method make iterations till an optimal basic feasible solution for it is obtained.
It may be noted that the new objective function W is always of minimization type regardless of
whether the given (original ) L.P.P. is of maximization or minimization type.
The Dual Simplex Method:The simplex method has been stated from the point of view of the
maximum problem. Clearly, it may be stated with regard to the minimum problem as well. In
particular, if a feasible vector has already been found for the minimum problem (i.e. the bottom
row is already nonnegative), it is more efficient to improve this vector with another feasible
vector than it is to apply the rule for Case 2 of the maximum problem. We state the simplex
method for the minimum problem.
Case 1: −c ≥ 0. Take any row with the last entry negative, say bi0 < 0. Among those j for which
ai0,j < 0, choose that j0 for which the ratio −cj/ai0,j is closest to zero. Pivot on ai0,j0 .
Case 2: Some −cj are negative. Take the first negative −cj, say −ck < 0 (where −c1 ≥ 0, . . .
,−ck−1 ≥ 0). Find any positive entry in column k, say ai0,k > 0. Compare −ck/ai0,k and those
−cj/ai0,j for which −cj ≥ 0 and ai0,j < 0, and choose j0 for which this ratio is closest to zero. (j0
may be k ). Pivot on ai0,j0 .
Example:
x1 x2 x3
y1 _−2 −1 −2 −1
y2 2 3 5 2
y3 −3 4 −1 1
1230
y1 x2 x3
x1 1/2
y2 1
y3 5/2
1/2 3/2 2 −1/2
26
If this example were treated as Case 2 for the maximum problem, we might pivot about the 4 or
the 5. Since we have a feasible vector for the minimum problem, we apply Case above, find a
unique pivot and arrive at the solution in one step.
For the linear programming problems below, state the dual problem, solve by the simplex (or
dual simplex) method, and state the solutions to both problems.
1. Maximize x1 − 2x2 − 3x3 − x4 subject to the constraints xj ≥ 0 for all j and
x1 − x2 − 2x3 − x4 ≤ 4
2x1 + x3 − 4x4 ≤ 2
−2x1 + x2 + x4 ≤ 1.
2. Minimize 3y1 − y2 + 2y3 subject to the constraints yi ≥ 0 for all i and
2y1 − y2 + y3 ≥ −1
y1 + 2y3 ≥ 2
−7y1 + 4y2 − 6y3 ≥ 1.
Program:
1.Two phase simplex
#include<iostream>
#include <vector>
#include <set>
#include <cmath>
#include <cstdlib>
using namespace std;
#define EPS 1E-9
#define DEBUG 0
int count;
inline int identity_col (const vector <vector <double> > & A, int c) {
int count = 0, row;
for (int r=0; r<A.size(); r++)
if (A[r][c] > EPS) { count++; row = r; }
return (count == 1) ? row : -1;
}
void canonicalize ( vector <vector <double> > & A,
vector <double>& B,
vector <double>& C,
vector <int>& BasicVarR, // basic variable of each row
double & obj // objective value
)
{
int m = A.size(), n = C.size();
for (int r=0; r<m; r++) {
int bc = BasicVarR[r]; // col. that the basic variable is in
if ( fabs(A[r][bc] - 1.0) > EPS) {
double p = A[r][bc];
for (int c=0; c<n; c++) A[r][c] /= p;
B[r] /= p;
}
if (fabs(C[bc]) > EPS) {
double p = C[bc];
for (int c=0; c<n; c++) C[c] -= A[r][c] * p;
obj -= B[r] * p;
}
}
}
bool pivoting ( vector <vector <double> > & A,
vector <double>& B,
vector <double>& C,
vector <int>& BasicVarR, // basic variable of each row
double & obj // objective value
)
{
int m = A.size(), n = C.size();
while (1) {
int ev = 0; // id of the entering variable
for (ev=0; ev<n; ev++)
if (C[ev] < -EPS) break;
if (ev == n) break; // optimum reached.
int lvr = -1; // leaving variable, id'ed by row
double minRatio;
for (int r=0; r<m; r++) {
if (A[r][ev] > EPS) {
if ( lvr < 0 || B[r]/A[r][ev] < minRatio ) {
lvr = r; minRatio = B[r] / A[r][ev];
}
}
}
if (lvr < 0) return true; // unbounded
int lv = BasicVarR[lvr]; // leaving variable
BasicVarR[lvr] = ev;
double p = A[lvr][ev];
for (int c=0; c<n; c++) A[lvr][c] /= p; B[lvr] /= p;
for (int r=0; r<m; r++) {
if ( r != lvr && fabs (A[r][ev]) > EPS ) {
double p2 = A[r][ev];
for (int c=0; c<n; c++) A[r][c] -= p2 * A[lvr][c];
B[r] -= p2 * B[lvr];
}
}
if ( fabs (C[ev]) > EPS ) {
double p2 = C[ev];
for (int c=0; c<n; c++) C[c] -= p2 * A[lvr][c];
obj -= p2 * B[lvr];
}
if (DEBUG) {
for (int c=0; c<n; c++) cout << C[c] << "\t"; cout << obj << endl;
for (int r=0; r<m; r++) {
for (int c=0; c<n; c++) cout << A[r][c] << "\t";
cout << B[r] << endl;
}
cout << endl;
}
}
return false;
}
void LU_solver ( vector <vector <double> > & A, // matrix A
vector <double>& B, // b
vector <double>& X // x
)
{
int n = A.size();
if (X.size() != n)
X.resize (n);
vector <vector <double> > L ( n, vector<double> (n) );
vector <vector <double> > U ( n, vector<double> (n) );
for (int i=0; i<n; i++)
L[i][i] = 1.0; // diagonals of L are 1's
copy ( A[0].begin(), A[0].end(), U[0].begin() );
for (int k=0; k<n-1; k++) {
for (int i=k+1; i<n; i++) { // compute the k'th column of L
double t = A[i][k];
for (int j=0; j<k; j++)
t -= ( L[i][j] * U[j][k] );
L[i][k] = t / U[k][k];
}
for (int j=k+1; j<n; j++) { // compute the (k+1)'s row of U
double t = A[k+1][j];
for (int i=0; i<k+1; i++)
t -= ( L[k+1][i] * U[i][j] );
U[k+1][j] = t;
}
}
for (int k=0; k<n; k++) {
X[k] = B[k];
for (int j=0; j<k; j++)
X[k] -= ( X[j] * L[k][j] );
}
for (int k=n-1; k>=0; k--) {
for (int j=k+1; j<n; j++)
X[k] -= ( X[j] * U[k][j] );
X[k] /= U[k][k];
}
}
int preprocess ( vector <vector <double> > & A, // constraint matrix
vector <double>& B, // right hand side
vector <double>& X // unknowns
)
{
int m = A.size (); // # of constraints
int n = A[0].size (); // # of variables
vector <bool> IsRedundant (m, false); // flags for redundant constraint
for (int r=0; r<m; r++) {
bool allZero = true;
for (int c=0; c<n; c++)
if (fabs(A[r][c]) > EPS) { allZero = false; break; }
if (allZero) {
if (fabs(B[r]) > EPS) return -1;
else IsRedundant[r] = true;
}
}
for (int i=0; i<m; i++) if (!IsRedundant[i]) {
for (int j=i+1; j<m; j++) if (!IsRedundant[j]) {
int c;
double ratio = 0.0;
for (c=0; c<n; c++) {
if ( fabs(A[i][c]) < EPS && fabs(A[j][c]) < EPS ) // both are 0
continue;
else if ( fabs(A[i][c]) < EPS && fabs(A[j][c]) > EPS || // one is 0
fabs(A[i][c]) > EPS && fabs(A[j][c]) < EPS )
break;
else { // both are nonzero
if ( fabs(ratio) < EPS )
ratio = A[i][c] / A[j][c];
else {
if ( fabs (A[i][c]/A[j][c] - ratio) > EPS )
break;
}
}
} if (c == n) {
if ( fabs(B[i]) < EPS && fabs(B[j]) < EPS ||
fabs(B[j]) > EPS && fabs (B[i]/B[j] - ratio) < EPS )
IsRedundant[j] = true;
else return -1; // inconsistency detected
}
}
}
int r;
for (int c=0; c<n; c++)
r = identity_col (A, c);
if(r==-1)
count==0;
else
count==1;
int numRedundancies = count;
if (numRedundancies > 0) {
int ir = 0; // 1 position to the right of the new A
for (int i=0; i<m; i++) {
if (!IsRedundant[i]) {
if (ir < i) { // overiding
copy (A[i].begin(), A[i].end(), A[ir].begin());
B[ir] = B[i];
}
ir++;
}
}
for (int i=0; i<numRedundancies; i++) {
A.erase (A.end()-1);
B.erase (B.end()-1);
}
}
m -= numRedundancies;
if (m >= n) { // determined or overdetermined system
vector <vector <double> > A0 (n, vector<double> (n));
vector <double> B0 (n);
for (int r=0; r<n; r++) {
copy (A[r].begin(), A[r].end(), A0[r].begin());
B0[r] = B[r];
}
LU_solver (A0, B0, X);
bool nonNegative = true;
for (int c=0; c<n; c++)
if (X[c] < 0) { nonNegative = false; break; }
if (!nonNegative)
return -1;
bool consistent = true;
for (int r=n; r<m; r++) {
double lhs = 0.0;
for (int c=0; c<n; c++)
lhs += A[r][c] * X[c];
if ( fabs (lhs - B[r]) > EPS ) { // constraint c not satisfied
consistent = false;
break;
}
}
return (consistent ? -2 : -1);
}
return numRedundancies;
}
int simplex ( const vector <vector <double> > & A, // constraint matrix
const vector <double>& B, // right hand side
const vector <double>& C, // objective vector
vector <double>& X, // unknowns
double & obj // objective value
)
{
int m = A.size(); // # of inequalities
int n = A[0].size(); // # of variables
if (!m || m != B.size() || n != C.size()) {
cout << "Wrong inputs!\n"; exit(1);
}
if (X.size() != n) X.resize(n);
fill (X.begin(), X.end(), 0);
vector <vector <double> > A0 ( m, vector<double>(n) );
vector <double> B0 (m);
for (int r=0; r<m; r++)
copy (A[r].begin(), A[r].end(), A0[r].begin() );
copy ( B.begin(), B.end(), B0.begin() );
int ret_val = preprocess (A0, B0, X);
int numRedundancies;
if (ret_val == -1) // inconsistent system
return -1;
else if (ret_val == -2) // solved
return 1;
else // need to run Simplex
numRedundancies = ret_val;
m = A0.size (); // size changes after redundancy removal
vector <bool> IsBasic (n, false); // bit flag for basic variables
vector <int> BasicVarR (m, -1); // basic variable of each row
int numBasicVar = 0;
for (int c=0; c<n; c++) {
int r = identity_col (A, c);
if (r >= 0 && BasicVarR[r] < 0) {
IsBasic[c] = true;
BasicVarR[r] = c;
numBasicVar++;
}
}
vector <vector <double> > A2 ( m, vector<double>(n) );
vector <double> B2 (m);
vector <double> C2 (n);
for (int r=0; r<m; r++)
copy ( A0[r].begin(), A0[r].end(), A2[r].begin() );
copy ( B0.begin(), B0.end(), B2.begin() );
for (int c=0; c<n; c++)
C2[c] = -C[c]; // obj. vector should be negated
obj = 0;
if (numBasicVar < m) {
int n1 = n; // Phase I need extra dummy variables
vector <vector <double> > A1 (m, vector<double>(n) );
vector <double> B1 (m);
vector <double> C1 (n, 0); // new objective vector for phase I
for (int r=0; r<m; r++)
copy ( A0[r].begin(), A0[r].end(), A1[r].begin() );
copy ( B0.begin(), B0.end(), B1.begin() ); // r.h.s. is the same
for (int i=0; i<m; i++) {
if (BasicVarR[i] < 0) {
for (int r=0; r<m; r++) {
if (r == i) A1[r].push_back (1);
else A1[r].push_back (0);
}
C1.push_back (1);
BasicVarR[i] = n1;
n1++;
}
}
C1.resize (n1, 1); // Adjust sizes of objective vector
canonicalize (A1, B1, C1, BasicVarR, obj); // convert to canonical form
bool unbounded = pivoting (A1, B1, C1, BasicVarR, obj); // pivoting
if (unbounded) {
cout << "Unbounded Phase I!" << endl;
exit (1);
} bool feasible = (fabs(obj) < EPS) ? true : false;
if (!feasible) return 0;
for (int r=0; r<m; r++) {
for (int c=0; c<n; c++)
A2[r][c] = A1[r][c];
B2[r] = B1[r];
}
}
canonicalize (A2, B2, C2, BasicVarR, obj);
bool unbounded = pivoting (A2, B2, C2, BasicVarR, obj);
for (int r=0; r<m; r++) // r.h.s. is the basic solution
X[BasicVarR[r]] = B2[r];
return ( unbounded ? -1 : 1 );
}
main()
{
int m, n;
while (1) {
cout << "How many constraints ? ";
cin >> m;
cout << "How many variables ? ";
cin >> n;
vector <vector <double> > A (m, vector<double>(n));
vector <double> B (m), C(n);
cout << "Enter the coefficients of the " << n <<" variables in the left hand side of equality
constraints:\n";
for (int i=0; i<m; i++) for (int j=0; j<n; j++) cin >> A[i][j];
cout << "Enter the constants on the right side of equality constraints:\n";
for (int i=0; i<m; i++) cin >> B[i];
cout << "Enter the coefficients of the" << n
<< " variables of the objective function:\n";
for (int i=0; i<n; i++) cin >> C[i];
vector <double> X;
double obj;
cout << simplex (A, B, C, X, obj) << endl;
cout << "\nOptimal objective value = " << obj << endl;
cout << "\nOptimal solution: ";
for (int i=0; i<n; i++)
cout << X[i] << "\t";
cout << endl;
}
}
2.Dual simplex
#include <stdio.h>
#include <math.h>
#define MMAX 25
#define NMAX 25
#define REAL double
2.Dual simplex
Conclusion: Hence WE have learned dual simplex method and implemented successfully.
Practical No. 2
Theory: The transportation problem is concerned with finding the minimum cost of transporting
a single commodity from a given number of sources (e.g. factories) to a given number of
destinations (e.g. warehouses). These types of problems can be solved by general network
methods, as in Chapter 9, but here we use a specific transportation algorithm. The data of the
model include 1. The level of supply at each source and the amount of demand at each
destination. 2. The unit transportation cost of the commodity from each source to each
destination. Since there is only one commodity, a destination can receive its demand from more
than one source. The objective is to determine how much should be shipped from each source to
each destination so as to minimise the total transportation cost.
Program:
#include <stdio.h>
#include <math.h>
#define NMAX 10
int P[5][2*NMAX+5];
int ID,IDES,IF1,IOPTIMAL,ISOU,IX,IY,LT,NR;
double CC,CT,QT,TT,XINFCC;
void Init() {
int I,J;
printf("\n TRANSPORT MODEL\n\n");
printf(" NUMBER OF SOURCES ? "); scanf("%d", &ISOU);
printf("\n NUMBER OF DESTINATIONS ? "); scanf("%d", &IDES);
printf("\n INPUT THE AVAILABLE SOURCE QUANTITIES:\n");
for (I=1; I<=ISOU; I++) {
printf(" SOURCE #%d ? ", I); scanf("%lf", &DAO[I]);
}
printf("\n INPUT THE REQUIRED DESTINATION QUANTITIES:\n");
for (I=1; I<=IDES; I++) {
printf(" DESTINATION #%d ? ", I); scanf("%lf", &RAD[I]);
}
printf("\n INPUT TRANSPORT COSTS MATRIX:\n");
for (I=1; I<=ISOU; I++)
for (J=1; J<=IDES; J++) {
printf(" FROM SOURCE #%d TO DESTINATION #%d ? ", I, J);
scanf("%lf", &C[I][J]);
}
printf("\n\n TRANSPORT MODEL\n");
}
void Corner();
void Optimal();
void TCost();
void Seek_Path(int I,int J);
void Increase(int I,int J);
void Optimal() {
//Labels: e10, e70, e140, e150
int I,J;
e10: XINFCC=0.0;
for (I=1; I<=ISOU; I++)
for (J=1; J<=IDES; J++) {
if (XM[I][J] != 0.0) goto e70;
Seek_Path(I,J);
Increase(I,J);
e70:; }
if (XINFCC>=0.0) {
IOPTIMAL=1;
goto e150;
}
for (I=1; I<=LT; I++) {
IX=P[3][I]; IY=P[4][I];
if (I % 2 == 0) {
XM[IX][IY] -= TT;
goto e140;
}
XM[IX][IY] += TT;
e140:;}
e150:if (IOPTIMAL==0) goto e10;
}
}
Output:
Theory:
Hungarian Method Algorithm:
Step 1: develop the cost table from the give problem
If no of rows does not equal to the no of columns and vise a versa, then a dummy row or
column must be added. The assignment cost for a dummy cells are 0.
Step 2: find the opportunity cost table;
1. Locate the smallest element in each row of the given cost table and then subtract that from
each element of the rows.
2. In the reduced matrix obtain from 2.1. locate the smallest element in each columns and then
subtract that from each element of that column each row and column now have at least one zero
value
Step 3: make assignment in the opportunity cost matrix
1.Examine rows successively until a row with exactly one unmarked zero is obtained make an
assignment to this single zero by making a square around it.
2.For each zero value that becomes assigned eliminate(X) strike off all other zero in the same
row and/or column.
3.Repeat step 3.1. and 3.2. for column also with exactly single zero value cell that has not been
assigned or eliminated.
4.If a row and/or columns has two or more unmarked zeros and one can not be chosen by
inspection, then choose the assigned zero cell arbitrarily.
5.Continue this process until all zeros in row/columns are either enclosed(assigned) or strike
off(X).
Step 4: optimality criterion
If the number of assignment cell is equal to the no. of row/columns then it is an optimal
solution the total cost associated with this solution is obtained by adding original cost
figure in the occupied cells
If a zero cell was chosen arbitrarily in step 3 there exists an alternative optimal solution
but if no optimal solution is found then go to step 5.
Step 5: revise the opportunity cost table
Draw a set of horizontal and vertical lines to cover all the zeros in the revised cost obtained from
step3 by using the following procedure.
1.For each row in which no allocation was made mark a tick.
2.Examine the marked row, if any zero in tick to the respective columns that contain zero.
3.Examine marked column. If any assigned zero occurs in those columns then tick the respective
rows that contain those assigned zero.
4.Repeat this process until no more row or columns can be marked
5.Draw a straight line through each marked column and each unmarked rows
If the no of line drawn is equal to the no. of rows then the current solution is the optimal solution
otherwise go to step 6.
Step 6: develop the new revised opportunity cost table
1.From among the cells not covered by any line, choose the smallest element call this value k.
2.Subtract k from every element in the cell not covered by a line.
3.Add k to every element in the cell covered by the two lines i.e. intersection of two line.
4.Elements in cell covered by one line remain unchanged
Step 7: repeat steps
Repeat step 3 to 6 until an optimal solution is obtained.
Program:
#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<iomanip.h>
#define MAX 50
enum boolean{FALSE,TRUE};
class HungarianMethod{
int data[MAX][MAX];
int allocation[MAX][MAX];
int no_of_rows,no_of_columns;
int bal_stat;
public:
HungarianMethod(){
int i,j;
for(i=0;i<MAX;i++){
for(j=0;j<MAX;j++){
data[i][j]=0;
allocation[i][j]=0;
}
}
no_of_rows=no_of_columns=bal_stat=0;
}
void setRow(int no){no_of_rows=no;}
void setColumn(int no){no_of_columns=no;}
void getData();
void makeAllocation();
void display();
void rowMinima(int [][MAX],int,int);
void columnMinima(int [][MAX],int,int);
boolean checkValue(int,int,int [][MAX]);
};
void HungarianMethod::getData(){
int i,j;
cout<<"enter cost Metrix :\n";
for(i=0;i<no_of_rows;i++){
cout<<"enter "<<i+1<<" row :";
for(j=0;j<no_of_columns;j++)
cin>>data[i][j];
}
}
void copyArray(int startRow,int startCol,int endRow,int endCol,int temp[][MAX],int
start1row,int start1col,int ans[][MAX]){
int i,j,k,l;
for(i=startRow,k=start1row;i<endRow;i++,k++)
for(j=startCol,l=start1col;j<endCol;j++,l++)
ans[k][l]=temp[i][j];
}
int getMinVal(int temp[],int no){
int min=temp[0];
for(int i=0;i<no;i++)
if(min>temp[i])
min=temp[i];
return min;
}
int getPosition(int temp[],int no,int value){
for(int i=0;i<no;i++)
if(temp[i]==value)
return i;
return -1;
}
int countVal(int temp[],int no,int value){
int i,sum=0;
for(i=0;i<no;i++)
if(temp[i]==value)
sum++;
return sum;
}
void HungarianMethod::rowMinima(int temp[][MAX],int row,int col){
int i,j,min;
for(i=0;i<row;i++){
min=9999;
for(j=0;j<col;j++)
if(min>temp[i][j])
min=temp[i][j];
for(j=0;j<col;j++)
temp[i][j]-=min;
}
}
void HungarianMethod::columnMinima(int temp[][MAX],int row,int col){
int i,j,min;
for(i=0;i<row;i++){
min=9999;
for(j=0;j<col;j++)
if(min>temp[j][i])
min=temp[j][i];
for(j=0;j<col;j++)
temp[j][i]-=min;
}
}
boolean HungarianMethod::checkValue(int row,int col,int temp[][MAX]){
int i,j;
for(i=0;i<row;i++)
for(j=0;j<col;j++)
if(temp[i][j]==0)
return TRUE;
return FALSE;
}
void HungarianMethod::makeAllocation(){
int temp_data[MAX][MAX]={0};
int i,j;
if(no_of_rows>no_of_columns){
for(i=0;i<no_of_rows;i++)
data[i][no_of_columns]=0;
no_of_columns++;
bal_stat=1;
}else if(no_of_rows<no_of_columns){
for(i=0;i<no_of_columns;i++)
data[no_of_rows][i]=0;
no_of_rows++;
bal_stat=2;
}
copyArray(0,0,no_of_rows,no_of_columns,data,0,0,temp_data);
rowMinima(temp_data,no_of_rows,no_of_columns);
columnMinima(temp_data,no_of_rows,no_of_columns);
int min,pos,count;
int tempCol[MAX]={0};
while(checkValue(no_of_rows,no_of_columns,temp_data)){
for(i=0;i<no_of_rows;i++){
count=countVal(temp_data[i],no_of_columns,0);
if(count==1){
pos=getPosition(temp_data[i],no_of_columns,0);
allocation[i][pos]=data[i][pos];
for(j=0;j<no_of_rows;j++)
if(temp_data[j][pos]==0)
temp_data[j][pos]=9999;
}
}
for(i=0;i<no_of_rows;i++){
for(j=0;j<no_of_columns;j++)
tempCol[j]=temp_data[j][i];
count=countVal(tempCol,no_of_rows,0);
if(count==1){
pos=getPosition(tempCol,no_of_rows,0);
allocation[i][pos]=data[i][pos];
for(j=0;j<no_of_columns;j++)
if(temp_data[pos][j]==0)
temp_data[pos][j]=9999;
}
}
}
}
void HungarianMethod::display(){
int i,j;
cout<<"\nGiven Cost Metrix :\n";
for(i=0;i<no_of_rows;i++)
cout<<"\t"<<char(65+i);
cout<<endl;
for(i=0;i<no_of_rows;i++){
cout<<i+1;
for(j=0;j<no_of_columns;j++)
cout<<"\t"<<data[i][j];
cout<<endl;
}
if(bal_stat!=0){
cout<<"\n\nhere the give cost metrix is not squar Matrix\n";
cout<<"so this is a unbalance problem and as a solution";
cout<<"\n we have add an extra "<<((bal_stat==1)?"column":"row")<<" with 0 value in
each\n";
}
cout<<"\n\nOpportunity Matrix :\n";
rowMinima(data,no_of_rows,no_of_columns);
columnMinima(data,no_of_rows,no_of_columns);
for(i=0;i<no_of_rows;i++){
for(j=0;j<no_of_columns;j++)
cout<<"\t"<<data[i][j];
cout<<endl;
}
int sum=0;
cout<<"\n\nJobs\t:\tMachine\t:\tCost\n";
for(i=0;i<no_of_rows;i++)
for(j=0;j<no_of_columns;j++)
if(allocation[i][j]!=0){
cout<<i+1<<"\t:\t"<<char(65+j)<<"\t:\t"<<allocation[i][j];
sum+=allocation[i][j];
cout<<endl;
}
cout<<"\nTotal Assignment Cost = "<<sum<<" RS.";
}
void main(){
clrscr();
HungarianMethod hm;
int row,col;
hm.setRow(row);
hm.setColumn(col);
hm.getData();
clrscr();
hm.makeAllocation();
hm.display();
getch();
}
Output:
Aim: Write a program for Critical path method/ programme evaluation review technique.
Theory:
PERT
Complex projects require a series of activities, some of which must be performed sequentially
and others that can be performed in parallel with other activities. This collection of series and
parallel tasks can be modeled as a network.
CPM is a deterministic method that uses a fixed time estimate for each activity. While CPM is
easy to understand and use, it does not consider the time variations that can have a great impact
on the completion time of a complex project.
The Program Evaluation and Review Technique (PERT) is a network model that allows for
randomness in activity completion times. It has the potential to reduce both the time and cost
required to complete a project.
The PERT chart may have multiple pages with many sub-tasks. The following is a very simple
example of a PERT diagram:
The milestones generally are numbered so that the ending node of an activity has a higher
number than the beginning node. Incrementing the numbers by 10 allows for new ones to be
inserted without modifying the numbering of the entire diagram. The activities in the above
diagram are labeled with letters along with the expected time required to complete the activity.
Steps in the PERT Planning Process
PERT planning involves the following steps:
Identify the specific activities and milestones.
Determine the proper sequence of the activities.
Most likely time - the completion time having the highest probability. Note that this time is
different from the expected time.
Pessimistic time - the longest time that an activity might require. Three standard deviations from
the mean is commonly used for the pessimistic time.
PERT assumes a beta probability distribution for the time estimates. For a beta distribution, the
expected time for each activity can be approximated using the following weighted average:
Expected time = ( Optimistic + 4 x Most likely + Pessimistic ) / 6
To calculate the variance for each activity completion time, if three standard deviation times
were selected for the optimistic and pessimistic times, then there are six standard deviations
between them, so the variance is given by:
[ ( Pessimistic - Optimistic ) / 6 ]2
Benefits of PERT
PERT is useful because it provides the following information:
Expected project completion time.
Probability of completion before a specified date.
The critical path activities that directly impact the completion time.
The activities that have slack time and that can lend resources to critical path activities.
Activity start and end dates.
Limitations
The following are some of PERT's weaknesses:
The activity time estimates are somewhat subjective and depend on judgement. In cases where
there is little experience in performing an activity, the numbers may be only a guess. In other
cases, if the person or group performing the activity estimates the time there may be bias in the
estimate.
Even if the activity times are well-estimated, PERT assumes a beta distribution for these time
estimates, but the actual distribution may be different.
Even if the beta distribution assumption holds, PERT assumes that the probability distribution of
the project completion time is the same as the that of the critical path. Because other paths can
become the critical path if their associated activities are delayed, PERT consistently
underestimates the expected project completion time.
The underestimation of the project completion time due to alternate paths becoming critical is
perhaps the most serious of these issues. To overcome this limitation, Monte Carlo simulations
can be performed on the network to eliminate this optimistic bias in the expected project
completion time.
Program:
#include <stdio.h>
#include <math.h>
#define NMAX 12
int K, N, NA;
double D[NMAX], TOT[NMAX], TARD[NMAX];
int ANTE[NMAX], PRED[NMAX];
int MARQ[3][NMAX];
double XTOT,XTARD;
Output:
Conclusion: Thus, we have learned and implemented critical path problem and PERT
successfully.
Practical no. 5
Problem: Given a complete undirected graph G=(V, E) that has nonnegative integer cost c(u, v)
associated with each edge (u, v) in E, the problem is to find a hamiltonian cycle (tour) of G with
minimum cost.
Description: A salespersons starts from the city 1 and has to visit six cities (1 through 6) and
must come back to the starting city i.e., 1. The first route (left side) 1→ 4 → 2 → 5 → 6 → 3 →
1 with the total length of 62 km, is a relevant selection but is not the best solution. The second
route (right side) 1 → 2 → 5 → 4 → 6 → 3 → 1 represents the must better solution as the total
distance, 48 km, is less than for the first route. Suppose c(A) denoted the total cost of the edges
in the subset A subset of E i.e., c(A) = ∑u,v in A c(u, v)
Moreover, the cost function satisfies the triangle inequality. That is, for all vertices u, v, w in V,
w have c(u, w) ≤ c(u, v) + c(v, w).
Note that the TSP problem is NP-complete even if we require that the cost function satisfies the
triangle inequality. This means that it is unlikely that we can find a polynomial-time algorithm
for TSP.
Program:
#include<stdio.h>
int cost=0;
main()
{
int n,a[10][10],visited[10];
printf("\nTravelling Salesman Problem Using Branch and Bound");
printf("\n**************************************************");
printf("\n Enter number of Cities:");
scanf("%d",&n);
get(a,n,visited);
mincost(1,n,a,visited);
put();
}
Output:
Conclusion: Thus, I have explained travelling sales problem and implemented program
successfully.
Practical No. 6
Suppose an investor has $100 on Monday. At the start of every day of the week (Monday
through Friday), the investor has the following investment opportunity available: If he invests x
dollars on that day and matches that initial investment with x/2 dollars the next day, then he will
receive a total return of 2x dollars on the third day.
Thus, with a total investment of 1.5×x dollars, the investor receives 2x dollars in two days, a gain
of 0.5 × x dollars. The investor wishes to determine an investment schedule that maximizes his
total cash on Saturday. To facilitate the formulation of a linear program, the investor decides to
make the following simplifying assumptions:
1. If an initial investment is not matched on the subsequent day, the initial investment is
lost.
2. Any return that is due on any given day can be reinvested immediately.
3. Cash carried forward from one day to the next does not accrue interest.
4. Borrowing money is not allowed.
Since a new investment cycle can, potentially, be initiated at the start of each day, the investor
needs to determine the magnitudes of these first installments. Therefore, let xj = the amount of
new investment at the beginning of Day j, j = 1, 2, 3, 4, where “Day 1” corresponds to Monday,
“Day 2” to Tuesday, and so on. Note that we did not introduce “x5” since it is unwise to initiate a
new investment cycle on Friday. We also assume that these decisions are to be made
immediately after receiving yields (if any) from prior investments.
In principle, it seems sufficient (and it is) to work with these four decision variables alone:
On Monday, we would invest x1 dollars and carry a cash saving of 100 − x1 forward to Tuesday.
On Tuesday, after executing a second installment of x1/2 dollars, we would have 100 − x1 −
x1/2 dollars available for an allocation of a new investment and a new cash saving. A little bit of
reflection should convince oneself that the picture would become rather complex as we move
further into future days. In particular, expressing the amount of cash saving at the end of each
day as a function of the entire history of past decisions quickly becomes a difficult task. From the
previous production-planning example, we learned that it is sometimes desirable tointroduce
additional sets of decision variables for the purpose of simplifying the formulation task. Now,
imagine yourself being at the start of a given day and ask: What actions do I need to take at this
point?
The answer is:
1. Cough up half of the amount of new investment (if any) that started in the previous day.
2. Initiate a new investment.
3. Carry the remaining cash (if any) forward to the next day.
Observe that these actions cannot be committed unless we know how much saving is being
carried forward from the previous day; and that this information depends on the entire prior
investment history in a complicated way. To circumvent this difficulty, it therefore seems
desirable to define a new set of variables to represent the daily savings.
Formally, let
sj = the amount of saving carried forward from Day j to Day j + 1, j = 1, 2, 3, 4, 5.
Note that we can think of the initial capital as a saving from Day 0 to Day 1; that is, let
s0 _ 100. In summary, we have defined a total of 9 decision variables, four xj ’s and five sj ’s.
On Saturday (Day 6), there are two income streams; one is the yield from the investment
cycle that started on Thursday and the other is the saving from Friday. The first contribution
equals 2x4 and the second, s5. It is important to realize that yields from all earlier investments
are “implicitly captured” into these two terms. Thus, our objective is to: Maximize 2x4 + s5 .
Note the simplicity of this objective function. It is a consequence of our “clever” choice of the
decision variables. In general, it is a good practice to conceptualize the formulation of the
decision variables and the objective function jointly.
The Constraints
In the alternative formulation of the production-planning problem, the production levels and the
ending inventory levels were linked together via constraints like yj = yj−1 +xj –dj to ensure that
they logically correspond to their intended interpretations. This can be viewed as “material”
balancing. Here again, we need to ensure proper linkage between the daily new investments and
the daily savings. The basic idea is to balance the cash flow at the beginning of each day. For
Day 1, we have s0 = 100 dollars available; and this amount is apportioned into two parts: a new
investment and a saving. Thus, s0 = x1 + s1. For Day 2, we have s1 dollars available; and this is
apportioned into three parts: x1/2, x2, and s2. Thus, s1 = 0.5x1 + x2 + s2. At the beginning of
Day 3, we receive a yield of 2x1, which is immediately available for reinvestment. It is therefore
added into s2; and the total amount is then divided into three parts as in Day 2. This leads to 2x1
+ s2 = 0.5x2 + x3 + s3 . Continuation of this argument yields 2x2 + s3 = 0.5x3 + x4 + s4 for Day
4 and, finally, 2x3 + s4 = 0.5x4 + s5 for Day 5. Note that the term “x5” does not appear in the
last equation. (What if we didn’t exclude this variable?) Clearly, the xj ’s must be nonnegative.
To ensure that we never over spend, the sj ’s are required to be nonnegative as well.
LP Formulation
It may be instructive to attempt to formulate this problem using the xj ’s only. Give it a try; it
would be quite messy. If we did not realize that x5 was unnecessary, then the fifth constraint
would have come out as 2x3 + s4 = 0.5x4 + x5 + s5. Consider an investment strategy that
prescribes, say,x5 = 5 and s5 = 10. We will argue that this strategy cannot be optimal. Observe
that the variable x5 appears only in the fifth constraint. Therefore, if we simply reset x5 to 0 and
s5 to 15 (maintaining the sum x5 +s5 at 15), then the resulting new strategy will have a better
objective function value (by how much?). This shows that it is never optimal to assign a positive
value to x5. We assumed that there is no reinvestment delay (Assumption 2). This assumption
can be easily relaxed. Suppose instead that there is a reinvestment delay of one day. This implies,
for example, that the yield 2x1 derived from the new investment on Day 1 won’t be available
until Day 4. Therefore, we should delete the term 2x1 from the left-hand side of the third
constraint and transfer this term to that of the fourth constraint. This results in revised constraints
s2 = 0.5x2 + x3 + s3 and 2x1 + s3 = 0.5x3 + x4 + s4. After making a similar revision in the fifth
constraint, we arrive at the following new formulation:
Maximize 2x4 + s5
Subject to:
s0 = x1 + s1
s1 = 0.5x1 + x2 + s2
s2 = 0.5x2 + x3 + s3
2x1 + s3 = 0.5x3 + x4 + s4
2x2 + s4 = 0.5x4 + s5
xj _ 0 for j = 1, 2, 3, 4 and sj _ 0 for j = 1, 2, 3, 4, 5 .
Note that it is not necessary to revise the objective function to 2x3 + s5.
Assumption 3 can also be relaxed. Suppose the daily interest rate is 1%. Then, our (original)
formulation revises to:
Maximize 2x4 + 1.01s5
Subject to:
s0 = x1 + s1
1.01s1 = 0.5x1 + x2 + s2
2x1 + 1.01s2 = 0.5x2 + x3 + s3
2x2 + 1.01s3 = 0.5x3 + x4 + s4
2x3 + 1.01s4 = 0.5x4 + s5
xj _ 0 for j = 1, 2, 3, 4 and sj _ 0 for j = 1, 2, 3, 4, 5,
where every daily saving grows by a factor of 1.01 overnight. If borrowing is allowed (see
Assumption 4), we can simply remove the nonnegativity requirements for the sj ’s. For realism,
we should, however, introduce some limits on loans, and incorporate that into the formulation in
the form of additional constraints. Otherwise,one would attempt to borrow an infinite amount of
money.
Program:
#include<stdio.h>
main()
{
int year, period ;
float amount, inrate, value ;
Output:
Theory: Decision theory, as it has grown up in recent years, is a formalization of the problems
involved in making optimal choices. In a certain sense—a very abstract sense, to be sure—it
incorporates operations research, theoretical economics, and wide areas of statistics, among
others. The formal structure of a decision problem in any area can be put into four parts: (1) the
choice of an objective function defining the relative desirability of different outcomes, (2)
specification of the policy alternatives which are available to the agent, or decisionmaker, (3)
specification of the model, that is, empirical relations that link the objective function, or the
variables that enter into it, with the policy alternatives and possibly other variables, and
(4) computational methods for choosing among the policy alternatives that one which performs
best as measured by the objective function
There are four types of criteria that we will look at.
Expected Value (Realist)
Compute the expected value under each action and then pick the action with the largest expected
value. This is the only method of the four that incorporates the probabilities of the states of
nature. The expected value criterion is also called the Bayesian principle.
Maximax (Optimist)
The maximax looks at the best that could happen under each action and then chooses the action
with the largest value. They assume that they will get the most possible and then they take the
action with the best best case scenario. The maximum of the maximums or the "best of the best".
This is the lotto player; they see large payoffs and ignore the probabilities.
Maximin (Pessimist)
The maximin person looks at the worst that could happen under each action and then choose the
action with the largest payoff. They assume that the worst that can happen will, and then they
take the action with the best worst case scenario. The maximum of the minimums or the "best of
the worst". This is the person who puts their money into a savings account because they could
lose money at the stock market.
Minimax (Opportunist)
Minimax decision making is based on opportunistic loss. They are the kind that look back after
the state of nature has occurred and say "Now that I know what happened, if I had only picked
this other action instead of the one I actually did, I could have done better". So, to make their
decision (before the event occurs), they create an opportunistic loss (or regret) table. Then they
take the minimum of the maximum. That sounds backwards, but remember, this is a loss table.
This similar to the maximin principle in theory; they want the best of the worst losses.
Program:
#include<iostream.h>
#include<conio.h>
#include<math.h>
class pract5
{
int i,j,arr[20][20],r,c, rmax,rmax1[10],rmin,rmin1[10];
int minimax, maximin;
public:
void getdata();
void calculate();
void display();
};
void pract5::getdata()
{
cout<<"\n Enter the no. of rows: ";
cin>>r;
cout<<"\n Enter the no. of columns: ";
cin>>c;
void pract5::calculate()
{
//logic for maximum from row
for(i=1; i<=r; i++)
{
rmax=arr[i][1];
for(j=1;j<=c;j++)
{
if(rmax <= arr[i][j] )
{
rmax=arr[i][j];
}
}
rmax1[i]=rmax;
}
cout<<"Maximum values form row:";
for(i=1;i<=r;i++)
{ cout<<"\n"<<rmax1[i]; }
}
cout<<"\n Value of Minimax is: "<<minimax;
}
cout<<"\n Value of Maximin is: "<<maximin;
void pract5::display()
{
cout<<"\n The given matrix is : \n ";
for(i=1; i<=r; i++)
{
for(j=1; j<=c; j++)
{
cout<<"\t"<<arr[i][j];
}
cout<<"\n";
}
}
void main()
{
clrscr();
pract5 obj;
obj.getdata();
obj.display();
obj.calculate();
getch();
}
Output:
Theory:
(a) Identify the smallest time element in the first column, i.e.for machine 1 let it be Ar
(b) .Identify the smallest time element in the third column, i.e.for machine 3, let it be Cr
(c) Identify the highest time element in the second column, i.e.for the center machine,
saymachine 2, let it be B
(d) Now minimum time on machine 1 i.e.Ar must be ≥ maximum time element on machine
2,i.e.
OR
Minimum time on third machine i.e.Cs must be ≥maximum time element on machine 2 i.e.Bi
OR
Both Ar and Cs must be ≥B
(e) If the above condition satisfies, then we have to workout the time elements for two
hypothetical machines, namely machine G and machine H. The time elements for machine G,
Gi= Ai+Bi.The time element for machine H, isHi= Bi+ Ci
(f) Now the three-machine problem is converted into two-machine problem. We can find
sequence by applying Johnson Bellman rule.
(g) All the assumption mentioned earlier will hold good in this case also
Program:
#include<iostream.h>
#include<conio.h>
void main()
{
int i,j,k,l,si,m;
char job[6]={'a','b','c','d','e','f'};
int m11[4],m12[4],m13[4];
int m1[4]={0,0,0,0};
int m2[4]={0,0,0,0};
int nm1[4]={0,0,0,0};
int nm2[4]={0,0,0,0};
char sq2[6],sq1[6];
int t1,t2,c,r1[3],r2[3];
int k=0,m=0,r=0,c=1;
clrscr();
cout<<"enter 1 to 4";
for(i=0;i<4;i++)
cin>>m11[i];
cout<<''enter for m12";
cin>>m12[i];
cout<<"enter for m13";
for(n2=0;n2<6;n2++)
{
m1[n2]=m11[n2]+m12[n2];
m2[n2]=m12[n2]+m13[n2];
}
for(c=1;c<7;c++)
{
if(c%2!=0)
{t=m1[i];si=1;
if(t==m1[i])
{
j=1;
if(m2[j]>m2[si])
t=m1[si];
else
{
t=m1[j];
si=j;
}
}
}
sq1[l]=job[si];
r1[l]=si;
m1[si]=32767;
l++;
}
else
{
t=m2[0];
for(i=1;i<6;i++)
{
if(t>m2[i])
{
t=m2[i];
si=i;
}
if(t==m2[i])
{
j=1;
if(m1[j]>m1[si])
t=m2[si];
else
{t=m2[j];si=j;}
}
sq2[m]=job[si];r2[m]=si;m2[si]32767;
m++;
}
}
for(n2=0;n2<6;n2++)
{
nm1[n2]=m11[n2]+m12[n2];
nm2[n2]=m12[n2]+m13[n2];
}
int tin1[6]={0,0,0,0,0,0};
int tin2[6]={0,0,0,0,0,0};
int tout1[6]={0,0,0,0,0,0};
int tout2[6]={0,0,0,0,0,0};
int idle[6]={0,0,0,0,0,0};
for(int t1=0;t1<3;t1++)
{
tout1[t1]=tin1[t1]+nm1[r1[t1]];
tin1[t1+1]=tout1[t1];
}
for(int t22=2,t3=3;t22>=0,t3<6;t22--,t3++)
{
tout1[t1]=tin1[t1]+nm1[r1[t1]];
tin1[t1+1]=tout1[t3];
nm2[r1[1]]=6;
tin2[0]=tout1[0];
for(int t4=0;t4<3;t4++)
{
tout2[t4]=tin2[t4]+nm2[r1[t4]];
if(tout1[t4+1]<tout2[t4])
tin2[t4+1]=tout2[t4];
else
tin2[t4+1]=tout1[t4+1];
cout<<"sequence";
for(int n=0;n<3;n++)
cout<<sq1[n]<<"/t";
for(int n=2;n>=0;n--)
cout<<"/n Processing time: /t"<<tout2[5]<<"units /n /n ";
cout<<"idle time"<<tout2[5]-tout1[5];
getch();
}}
Output:
enter 1 to 4
2 3
1 4
enter for m12
3 2
4 5
enter for m13
1 4
2 5
sequence
3 2 4 1
processing time:5
idle time 5-3
processing time:12
idle time 12-8
processing time:18
idle time 18-13
processing time:19
idle time 19-16
Theory:
Inventory Model
Inventory refers to idle goods or materials that are held by an organization for use sometime in
future.
• Raw materials
• Purchased parts
• Components
• Subassemblies
• Work-in-process
• Finished goods
Key issues:
A business requires reasonable amount of inventory to ensure smooth operation. The inventory
problem determines the inventory levels that balances the two extremes ( too much and too little
).The factors that apply in solving the inventory is the demand for an item may be deterministic (
identified with certainty) or probabilistic ( portrayed by a probability solution).
General Inventory Model
The cycle for inventory model is placing and receiving order. This working activity is applied
with the inquiries
i. How much to order?
ii. When to order?
The above questions are answered by minimizing the following cost model.
Total Inventory Cost = (Purchasing Cost) + (Setup Cost) + (Holding Cost) + (Shortage Cost).
The above equation reflects the instantaneous arrival of order on placement .Instead a positive
lead time L may occur between the placement and receipt of an order. In this case a reorder point
occurs when the inventory level drops to LD units. Now effective lead time becomes Le = L- nt0
Where n is the largest integer no exceeding L/ t0.The following figure provides the pictorial
representation of the static EOQ method.
The realistic inventory model. Q = order batch size, B = order point, S = the buffer inventory, L
= order lead-time.
Probability is associated with performing an experiment whose outcome occurs randomly. The
conjunction of all the outcomes of an experiment is referred to as the sample space and subset of
the sample space is known as an event.
The developed probabilistic model is broadly categorized under continuous and (Single & Multi)
periodic review situations.
It is given by,
P {XL ≥ B + µL} ≤ α
Where
L = Lead Time
XL = Random variable representing demand during lead time.
µL = Average demand during lead time.
B = Buffer stock value.
α = Max allowable probability of running out of stock during lead time.
The main assumption in this model is XL the demand during lead time L it is normally
distributed with the mean and standard deviation during lead time (σL).
Program:
Output:
Theory:
Game theory studies situations in which parties compete, and also possibly cooperate, to
influence the outcome of the parties' interaction to each party's advantage. The situation involves
conflict between the participants — called players — because some outcomes favor one player at
the expense of the other players. What each player obtains from a particular outcome is called
the player's pay-off. Each player can choose among a number of actions to influence his pay-off.
However, each player's pay-off depends on the other players' choices. Moreover, outcomes can
also be influenced by "chance occurrences."
program
#include<stdio.h>
#include<conio.h>
void main()
{
float i,j,game[2][2];
float p1,p2,q1,q2,ev;
clrscr();
printf("\n please enter the game sequence row wise\n");
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
scanf("%f", &game[i][j]);
}
printf("\n The given game sequence is:\n");
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
printf("%f\t",game[i][j]);
printf("\n");
}
p1=((game[1][1]-game[1][0]))|(game[0][0]+game[1][1]-game[0][1]-game[1][0]));
p2=1-p1;
q1=((game[1][1]-game[0][1]))|(game[0][0]+game[1][0]-game[0][1]-game[1][0]));
q2=1-q1;
ev=((game[0][0]-game[1][1]))-(game[0][1]*game[1][0]))|(game[0][0]+game[1][1]-game[0][1]-
game[1][0]));
printf("\n the best winning strategy for player b is:%f\n%5f\n",a1,a2);
printf("\n the estimated game value is %f\n",ev);
getch();
}
output: