// Simplex method v2.01 (Feng Xie, xief@mcmaster.ca) // // simplex (vector> A, vector B, vector C, // vector X, double obj); // Input: A - constraint matrix in standard form (equality); // B - right hand side, should be non-negative; // C - objective vector. // Output: X - optimal solution; obj - optimal value; // Returns: -1 - unbounded; 0 - infeasible; 1 - feasible & bounded. // Note: it solves a maximization problem. #include #include #include #include using namespace std; #define EPS 1E-9 #define DEBUG 0 // Check if column c of A is an indentity column. // Returns: -1 if not; non-zero row id otherwise. inline int identity_col (const vector > & A, int c) { int count = 0, row; for (int r=0; r EPS) { count++; row = r; } return (count == 1) ? row : -1; } // Convert a standard form of LP into canonical form: // 1) The entries in the objective vector corresponding to basic variables are // 0's. // 2) The submatrix corresponding to basic variables is an identity matrix. void canonicalize ( vector > & A, vector & B, vector & C, vector & BasicVarR, // basic variable of each row double & obj // objective value ) { int m = A.size(), n = C.size(); for (int r=0; r EPS) { double p = A[r][bc]; for (int c=0; c EPS) { double p = C[bc]; for (int c=0; c > & A, vector & B, vector & C, vector & BasicVarR, // basic variable of each row double & obj // objective value ) { int m = A.size(), n = C.size(); while (1) { // Find the entering variable (use the first one encountered). int ev = 0; // id of the entering variable for (ev=0; 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 // Leaving & entering variables identified, do pivoting. BasicVarR[lvr] = ev; double p = A[lvr][ev]; for (int c=0; c EPS ) { double p2 = A[r][ev]; for (int c=0; c EPS ) { double p2 = C[ev]; for (int c=0; c > & A, // matrix A vector & B, // b vector & X // x ) { int n = A.size(); if (X.size() != n) X.resize (n); vector > L ( n, vector (n) ); vector > U ( n, vector (n) ); // LU decomposition (Dolittle's method). for (int i=0; i=0; k--) { for (int j=k+1; j=0 : otherwise indicate the # of redundancies removed. int preprocess ( vector > & A, // constraint matrix vector & B, // right hand side vector & X // unknowns ) { int m = A.size (); // # of constraints int n = A[0].size (); // # of variables vector IsRedundant (m, false); // flags for redundant constraint // Remove all-zero rows. for (int r=0; r EPS) { allZero = false; break; } if (allZero) { if (fabs(B[r]) > EPS) return -1; else IsRedundant[r] = true; } } for (int i=0; i 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 numRedundancies = count (IsRedundant.begin(), IsRedundant.end(), true); // Remove the redundant constraints. if (numRedundancies > 0) { int ir = 0; // 1 position to the right of the new A for (int i=0; i= n) { // determined or overdetermined system // A0, B0, X0 : for LU solver. vector > A0 (n, vector (n)); vector B0 (n); for (int r=0; r EPS ) { // constraint c not satisfied consistent = false; break; } } return (consistent ? -2 : -1); } return numRedundancies; } // Simplex method (primal). // Returns: -1 - unbounded; 0 - infeasible; 1 - feasible & bounded. int simplex ( const vector > & A, // constraint matrix const vector & B, // right hand side const vector & C, // objective vector vector & X, // unknowns double & obj // objective value ) { int m = A.size(); // # of inequalities int n = A[0].size(); // # of variables // Sanity check. if (!m || m != B.size() || n != C.size()) { cout << "Wrong inputs!\n"; exit(1); } // Adjust size of X if necessary. if (X.size() != n) X.resize(n); fill (X.begin(), X.end(), 0); // A0, B0 : for preprocessing vector > A0 ( m, vector(n) ); vector B0 (m); for (int r=0; r IsBasic (n, false); // bit flag for basic variables vector BasicVarR (m, -1); // basic variable of each row // Find the initial basic variables. int numBasicVar = 0; for (int c=0; c= 0 && BasicVarR[r] < 0) { IsBasic[c] = true; BasicVarR[r] = c; numBasicVar++; } } // A2, B2, C2 : for Phase II vector > A2 ( m, vector(n) ); vector B2 (m); vector C2 (n); for (int r=0; r > A1 (m, vector(n) ); vector B1 (m); vector C1 (n, 0); // new objective vector for phase I for (int r=0; r> m; cout << "Input the number of variables: "; cin >> n; vector > A (m, vector(n)); vector B (m), C(n); cout << "Input the " << m << " by " << n << " coefficients of the LHS of equality constraints:\n"; for (int i=0; i> A[i][j]; cout << "Input the " << m << " constants of the RHS of equality constraints:\n"; for (int i=0; i> B[i]; cout << "Input the " << n << " coefficients of the objective function:\n"; for (int i=0; i> C[i]; vector 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