├── .gitattributes ├── README.md ├── codes ├── appendix A │ ├── example1a.m │ ├── example1b.m │ ├── example2a.m │ ├── example2b.m │ └── linprogSolver.m ├── appendix B │ ├── clpOptimizer.m │ └── cplexOptimizer.m ├── benchmarkLPs │ ├── MAT │ │ ├── beaconfd.mat │ │ ├── cari.mat │ │ ├── farm.mat │ │ ├── itest6.mat │ │ ├── klein2.mat │ │ ├── nsic1.mat │ │ ├── nsic2.mat │ │ ├── osa-07.mat │ │ ├── osa-14.mat │ │ ├── osa-30.mat │ │ ├── rosen1.mat │ │ ├── rosen10.mat │ │ ├── rosen2.mat │ │ ├── rosen7.mat │ │ ├── rosen8.mat │ │ ├── sc205.mat │ │ ├── scfxm1.mat │ │ ├── sctap2.mat │ │ └── sctap3.mat │ └── MPS │ │ ├── beaconfd.mps │ │ ├── cari.mps │ │ ├── farm.mps │ │ ├── itest6.mps │ │ ├── klein2.mps │ │ ├── nsic1.mps │ │ ├── nsic2.mps │ │ ├── osa-07.mps │ │ ├── osa-14.mps │ │ ├── osa-30.mps │ │ ├── rosen1.mps │ │ ├── rosen10.mps │ │ ├── rosen2.mps │ │ ├── rosen7.mps │ │ ├── rosen8.mps │ │ ├── sc205.mps │ │ ├── scfxm1.mps │ │ ├── sctap2.mps │ │ └── sctap3.mps ├── chapter10 │ ├── epsa.m │ └── lprref.m ├── chapter11 │ └── ipdipm.m ├── chapter12 │ ├── sensitivityAnalysis.m │ ├── sensitivityAnalysisAddConstraint.m │ ├── sensitivityAnalysisAddVariable.m │ ├── sensitivityAnalysisChangeb.m │ ├── sensitivityAnalysisChangec.m │ ├── sensitivityAnalysisb.m │ └── sensitivityAnalysisc.m ├── chapter2 │ ├── canonical2standard.m │ ├── example1.mn │ ├── example2.mn │ ├── example3.mn │ ├── general2canonical.m │ ├── general2standard.m │ ├── primal2dual.m │ └── standard2canonical.m ├── chapter3 │ ├── GenerateRandomLPs.m │ ├── denseMenu.m │ ├── denseRandom.m │ ├── denseRandomOptimal.m │ ├── example1_1.mps │ ├── example1_2.mps │ ├── example1_3.mps │ ├── example2.mps │ ├── mat2mps.m │ ├── mps2mat.m │ ├── sparseMenu.m │ ├── sparseRandom.m │ └── sparseRandomOptimal.m ├── chapter4 │ ├── eliminateDualSingletonInequalityConstraints.m │ ├── eliminateImpliedBoundsonRows.m │ ├── eliminateImpliedFreeSingletonColumns.m │ ├── eliminateKtonEqualityConstraints.m │ ├── eliminateRedundantColumns.m │ ├── eliminateRedundantRows.m │ ├── eliminateSingletonEqualityConstraints.m │ ├── eliminateSingletonInequalityConstraints.m │ ├── eliminateZeroColumns.m │ ├── eliminateZeroRows.m │ ├── fullRank.m │ └── presolve.m ├── chapter5 │ ├── arithmeticMean.m │ ├── debuchet1.m │ ├── debuchet2.m │ ├── debuchetinf.m │ ├── entropy.m │ ├── equilibration.m │ ├── geometricMean.m │ ├── ibmmpsx.m │ ├── lpnorm1.m │ ├── lpnorm2.m │ └── lpnorminf.m ├── chapter6 │ ├── bland.m │ ├── dantzig.m │ ├── gim.m │ ├── lrcm.m │ ├── partialPricing.m │ ├── partialPricingInitial.m │ ├── partialPricingUpdate.m │ └── steepestEdge.m ├── chapter7 │ ├── gaussjordanElimination.m │ ├── luInverse.m │ ├── mpfi.m │ └── pfi.m ├── chapter8 │ ├── lprref.m │ └── rsa.m └── chapter9 │ ├── lprref.m │ └── rdsa.m ├── contributing.md ├── cover.jpg ├── errata.md └── license.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Springer Source Code 2 | 3 | This repository accompanies *Linear Programming Using MATLAB®* by Nikolaos Ploskas and Nikolaos Samaras (Springer, 2018). 4 | 5 | ![Cover Image](cover.jpg) 6 | 7 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 8 | 9 | ## Releases 10 | 11 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 12 | 13 | ## Corrections 14 | 15 | For corrections to the content in the published book, see the file errata.md. 16 | 17 | ## Contributions 18 | 19 | See the file Contributing.md for more information on how you can contribute to this repository. 20 | -------------------------------------------------------------------------------- /codes/appendix A/example1a.m: -------------------------------------------------------------------------------- 1 | variables = {'x1', 'x2', 'x3', 'x4'}; % construct a cell 2 | % array with the names of the variables 3 | n = length(variables); % find the number of the variables 4 | for i = 1:n % create x for indexing 5 | eval([variables{i}, ' = ', num2str(i), ';']); 6 | end 7 | lb = zeros(1, n); % create a vector and add a lower bound 8 | % of zero to all variables 9 | lb([x1, x3]) = [1, 2]; % add lower bounds to variables x1, 10 | % x3 11 | ub = Inf(1, n); % create a vector and add an upper bound of 12 | % Inf to all variables 13 | ub(x3) = 10; % add an upper bound to variable x3 14 | A = zeros(2, n); % create the matrix A 15 | b = zeros(2, 1); % create the vector b 16 | % declare the 1st constraint 17 | A(1, [x1, x3]) = [-2, -3]; b(1) = -6; 18 | % declare the 2nd constraint 19 | A(2, [x1, x2, x4]) = [-3, 2, -4]; b(2) = -8; 20 | Aeq = zeros(2, n); % create the matrix Aeq 21 | beq = zeros(2, 1); % create the vector beq 22 | % declare the 1st equality constraint 23 | Aeq(1, [x1, x2, x3, x4]) = [4, -3, 8, -1]; beq(1) = 20; 24 | % declare the 2nd equality constraint 25 | Aeq(2, [x1, x3, x4]) = [4, -1, 4]; beq(2) = 18; 26 | c = zeros(n, 1); % create the objective function vector c 27 | c([x1 x2 x3 x4]) = [-2; 4; -2; 2]; 28 | % call the linprog solver 29 | [x, objVal] = linprog(c, A, b, Aeq, beq, lb, ub); 30 | for i = 1:n % print results in formatted form 31 | fprintf('%s \t %20.4f\n', variables{i}, x(i)) 32 | end 33 | fprintf(['The value of the objective function ' ... 34 | 'is %.4f\n'], objVal) -------------------------------------------------------------------------------- /codes/appendix A/example1b.m: -------------------------------------------------------------------------------- 1 | A = [-2 0 -3 0; -3 2 0 -4]; % create the matrix A 2 | b = [-6; -8]; % create the vector b 3 | Aeq = [4 -3 8 -1; 4 0 -1 4]; %create the matrix Aeq 4 | beq = [20; 18]; % create the vector beq 5 | lb = [1 0 2 0]; % create the vector lb 6 | ub = [Inf Inf 10 Inf]; % create the vector ub 7 | c = [-2; 4; -2; 2]; %create the vector c 8 | % call the linprog solver 9 | [x, objVal] = linprog(c, A, b, Aeq, beq, lb, ub); 10 | for i = 1:4 % print results in formatted form 11 | fprintf('x%d \t %20.4f\n', i, x(i)) 12 | end 13 | fprintf(['The value of the objective function ' ... 14 | 'is %.4f\n'], objVal) -------------------------------------------------------------------------------- /codes/appendix A/example2a.m: -------------------------------------------------------------------------------- 1 | variables = {'x1', 'x2', 'x3', 'x4', 'x5'}; % construct a 2 | % cell array with the names of the variables 3 | n = length(variables); % find the number of the variables 4 | for i = 1:n % create x for indexing 5 | eval([variables{i}, ' = ', num2str(i), ';']); 6 | end 7 | lb = zeros(1, n); % create a vector and add a lower bound 8 | % of zero to all variables 9 | lb([x1, x2]) = [5, 1]; % add lower bounds to variables x1, 10 | % x2 11 | ub = Inf(1, n); % create a vector and add an upper bound 12 | % of Inf to all variables 13 | A = zeros(3, n); % create the matrix A 14 | b = zeros(3, 1); % create the vector b 15 | % declare the 1st inequality constraint 16 | A(1, [x1, x2, x3, x4]) = [1, 4, -2, -1]; b(1) = 8; 17 | % declare the 2nd inequality constraint 18 | A(2, [x1, x2, x3, x4]) = [1, 3, 2, -1]; b(2) = 10; 19 | % declare the 3rd inequality constraint 20 | A(3, [x1, x2, x3, x4, x5]) = [2, 1, 2, 3, -1]; b(3) = 20; 21 | Aeq = zeros(1, n); % create the matrix Aeq 22 | beq = zeros(1, 1); % create the vector beq 23 | % declare the equality constraint 24 | Aeq(1, [x1, x2, x3, x4, x5]) = [1, 3, -4, -1, 1]; beq(1) = 7; 25 | c = zeros(n, 1); % create the objective function vector c 26 | c([x1 x2 x3 x4 x5]) = [-2; -3; 1; 4; 1]; 27 | % call the linprog solver 28 | [x, objVal] = linprog(c, A, b, Aeq, beq, lb, ub); 29 | for i = 1:n % print results in formatted form 30 | fprintf('%s \t %20.4f\n', variables{i}, x(i)) 31 | end 32 | fprintf(['The value of the objective function ' ... 33 | 'is %.4f\n'], objVal) -------------------------------------------------------------------------------- /codes/appendix A/example2b.m: -------------------------------------------------------------------------------- 1 | A = [1 4 -2 -1 0; 1 3 2 -1 0; 2 1 2 3 -1]; % create the matrix A 2 | b = [8; 10; 20]; % create the vector b 3 | Aeq = [1 3 -4 -1 1]; %create the matrix Aeq 4 | beq = [7]; % create the vector beq 5 | lb = [5 1 0 0 0]; % create the vector lb 6 | ub = [Inf Inf Inf Inf Inf]; % create the vector ub 7 | c = [-2; -3; 1; 4; 1]; %create the vector c 8 | % call the linprog solver 9 | [x, objVal] = linprog(c, A, b, Aeq, beq, lb, ub); 10 | for i = 1:5 % print results in formatted form 11 | fprintf('x%d \t %20.4f\n', i, x(i)) 12 | end 13 | fprintf(['The value of the objective function ' ... 14 | 'is %.4f\n'], objVal) -------------------------------------------------------------------------------- /codes/appendix A/linprogSolver.m: -------------------------------------------------------------------------------- 1 | function [xsol, fval, exitflag, iterations] = ... 2 | linprogSolver(A, c, b, Eqin, MinMaxLP, c0, ... 3 | algorithm) 4 | % Filename: linprogSolver.m 5 | % Description: the function is a MATLAB code to solve LPs 6 | % using the linprog solver 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [x, fval, exitflag, iterations] = ... 10 | % linprogSolver(A, c, b, Eqin, MinMaxLP, c0, ... 11 | % algorithm) 12 | % 13 | % Input: 14 | % -- A: matrix of coefficients of the constraints 15 | % (size m x n) 16 | % -- c: vector of coefficients of the objective function 17 | % (size n x 1) 18 | % -- b: vector of the right-hand side of the constraints 19 | % (size m x 1) 20 | % -- Eqin: vector of the type of the constraints 21 | % (size m x 1) 22 | % -- MinMaxLP: the type of optimization (optional: 23 | % default value -1 - minimization) 24 | % -- c0: constant term of the objective function 25 | % (optional: default value 0) 26 | % -- algorithm: the LP algorithm that will be used 27 | % (possible values: 'interior-point', 'dual-simplex', 28 | % 'simplex', 'active-set') 29 | % 30 | % Output: 31 | % -- xsol: the solution found by the solver (size m x 1) 32 | % -- fval: the value of the objective function at the 33 | % solution xsol 34 | % -- exitflag: the reason that the algorithm terminated 35 | % (1: the solver converged to a solution x, 0: the 36 | % number of iterations exceeded the MaxIter option, 37 | % -1: the input data is not logically or numerically 38 | % correct, -2: no feasible point was found, -3: the LP 39 | % problem is unbounded, -4: NaN value was encountered 40 | % during the execution of the algorithm, -5: both primal 41 | % and dual problems are infeasible, -7: the search 42 | % direction became too small and no further progress 43 | % could be made) 44 | % -- iterations: the number of iterations 45 | 46 | % set default values to missing inputs 47 | if ~exist('MinMaxLP') 48 | MinMaxLP = -1; 49 | end 50 | if ~exist('c0') 51 | c0 = 0; 52 | end 53 | [m, n] = size(A); % find the size of matrix A 54 | [m2, n2] = size(c); % find the size of vector c 55 | [m3, n3] = size(Eqin); % find the size of vector Eqin 56 | [m4, n4] = size(b); % find the size of vector b 57 | % check if input data is logically correct 58 | if n2 ~= 1 59 | disp('Vector c is not a column vector.') 60 | exitflag = -1; 61 | return 62 | end 63 | if n ~= m2 64 | disp(['The number of columns in matrix A and ' ... 65 | 'the number of rows in vector c do not match.']) 66 | exitflag = -1; 67 | return 68 | end 69 | if m4 ~= m 70 | disp(['The number of the right-hand side values ' ... 71 | 'is not equal to the number of constraints.']) 72 | exitflag = -1; 73 | return 74 | end 75 | if n3 ~= 1 76 | disp('Vector Eqin is not a column vector') 77 | exitflag = -1; 78 | return 79 | end 80 | if n4 ~= 1 81 | disp('Vector b is not a column vector') 82 | exitflag = -1; 83 | return 84 | end 85 | if m4 ~= m3 86 | disp('The size of vectors Eqin and b does not match') 87 | exitflag = -1; 88 | return 89 | end 90 | % if the problem is a maximization problem, transform it to 91 | % a minimization problem 92 | if MinMaxLP == 1 93 | c = -c; 94 | end 95 | Aeq = []; % matrix constraint of equality constraints 96 | beq = []; % right-hand side of equality constraints 97 | % check if all constraints are equalities 98 | flag = isequal(zeros(m3, 1), Eqin); 99 | if flag == 0 % some or all constraints are inequalities 100 | indices = []; % indices of the equality constraints 101 | for i = 1:m3 102 | if Eqin(i, 1) == 0 % find the equality constraints 103 | indices = [indices i]; 104 | % convert 'greater than or equal to' type of 105 | % constraints to 'less than or equal to' type 106 | % of constraints 107 | elseif Eqin(i, 1) == 1 108 | A(i, :) = -A(i, :); 109 | b(i) = -b(i); 110 | end 111 | end 112 | % create the matrix constraint of equality constraints 113 | Aeq = A(indices, :); 114 | A(indices, :) = []; % delete equality constraints 115 | % create the right-hand side of equality constraints 116 | beq = b(indices); 117 | b(indices) = []; % delete equality constraints 118 | else % all constraints are equalities 119 | Aeq = A; 120 | beq = b; 121 | A = []; 122 | b = []; 123 | end 124 | lb = zeros(n, 1); % create zero lower bounds 125 | % choose LP algorithm 126 | options = optimoptions(@linprog, 'Algorithm', algorithm); 127 | % call the linprog solver 128 | [xsol, fval, exitflag, output] = linprog(c, A, b, ... 129 | Aeq, beq, lb, [], [], options); 130 | iterations = output.iterations; 131 | % calculate the value of the objective function 132 | if MinMaxLP == 1 % maximization 133 | fval = -(fval + c0); 134 | else % minimization 135 | fval = fval + c0; 136 | end 137 | end -------------------------------------------------------------------------------- /codes/appendix B/clpOptimizer.m: -------------------------------------------------------------------------------- 1 | function [xsol, fval, exitflag, iterations] = ... 2 | clpOptimizer(mpsFullPath, algorithm, primalTol, ... 3 | dualTol, maxIter, maxTime, displayLevel, objBias, ... 4 | numPresolvePasses, factorFreq, numberRefinements, ... 5 | primalObjLim, dualObjLim, numThreads, abcState) 6 | % Filename: clpOptimizer.m 7 | % Description: the function is a MATLAB code to solve LPs 8 | % using CLP (via OPTI Toolbox) 9 | % Authors: Ploskas, N., & Samaras, N. 10 | % 11 | % Syntax: [xsol, fval, exitflag, iterations] = ... 12 | % clpOptimizer(mpsFullPath, algorithm, primalTol, ... 13 | % dualTol, maxIter, maxTime, display, objBias, ... 14 | % numPresolvePasses, factorFreq, numberRefinements, ... 15 | % primalObjLim, dualObjLim, numThreads, abcState) 16 | % 17 | % Input: 18 | % -- mpsFullPath: the full path of the MPS file 19 | % -- algorithm: the CLP algorithm that will be used 20 | % (optional, possible values: 'DualSimplex', 21 | % 'PrimalSimplex', 'PrimalSimplexOrSprint', 22 | % 'Barrier', 'BarrierNoCross', 'Automatic') 23 | % -- primalTol: the primal tolerance (optional) 24 | % -- dualTol: the dual tolerance (optional) 25 | % -- maxIter: the maximum number of iterations 26 | % -- (optional) 27 | % -- maxTime: the maximum execution time in seconds 28 | % -- (optional) 29 | % -- displayLevel: the display level (optional, 30 | % possible values: 0, 1 -> 100 increasing) 31 | % -- objBias: the objective bias term (optional) 32 | % -- numPresolvePasses: the number of presolver passes 33 | % (optional) 34 | % -- factorFreq: every factorFreq number of iterations, 35 | % the basis inverse is re-computed from scratch 36 | % (optional) 37 | % -- numberRefinements: the number of iterative simplex 38 | % refinements (optional) 39 | % -- primalObjLim: the primal objective limit (optional) 40 | % -- dualObjLim: the dual objective limit (optional) 41 | % -- numThreads: the number of Cilk worker threads 42 | % (optional, only with Aboca CLP build) 43 | % -- abcState: Aboca's partition size (optional) 44 | % 45 | % Output: 46 | % -- xsol: the solution found by the solver (size m x 1) 47 | % -- fval: the value of the objective function at the 48 | % solution xsol 49 | % -- exitflag: the reason that the algorithm terminated 50 | % (1: the solver converged to a solution x, 0: the 51 | % number of iterations exceeded the maxIter option or 52 | % time reached, -1: the LP problem is infeasible or 53 | % unbounded) 54 | % -- iterations: the number of iterations 55 | 56 | % set user defined values to options 57 | opts = optiset('solver', 'clp'); 58 | if exist('algorithm') 59 | opts.solverOpts.algorithm = algorithm; 60 | end 61 | if exist('primalTol') 62 | opts.solverOpts.primalTol = primalTol; 63 | opts.tolrfun = primalTol; 64 | end 65 | if exist('dualTol') 66 | opts.solverOpts.dualTol = dualTol; 67 | end 68 | if exist('maxIter') 69 | opts.maxiter = maxIter; 70 | else 71 | opts.maxiter = 1000000; 72 | end 73 | if exist('maxTime') 74 | opts.maxtime = maxTime; 75 | else 76 | opts.maxtime = 1000000; 77 | end 78 | if exist('displayLevel') 79 | opts.display = displayLevel; 80 | end 81 | if exist('objBias') 82 | opts.solverOpts.objbias = objBias; 83 | end 84 | if exist('numPresolvePasses') 85 | opts.solverOpts.numPresolvePasses = numPresolvePasses; 86 | end 87 | if exist('factorFreq') 88 | opts.solverOpts.factorFreq = factorFreq; 89 | end 90 | if exist('numberRefinements') 91 | opts.solverOpts.numberRefinements = numberRefinements; 92 | end 93 | if exist('primalObjLim') 94 | opts.solverOpts.primalObjLim = primalObjLim; 95 | end 96 | if exist('dualObjLim') 97 | opts.solverOpts.dualObjLim = dualObjLim; 98 | end 99 | if exist('numThreads') 100 | opts.solverOpts.numThreads = numThreads; 101 | end 102 | if exist('abcState') 103 | opts.solverOpts.abcState = abcState; 104 | end 105 | % read the MPS file 106 | prob = coinRead(mpsFullPath); 107 | % call CLP solver 108 | [xsol, fval, exitflag, info] = opti_clp([], prob.f, ... 109 | prob.A, prob.rl, prob.ru, prob.lb, prob.ub, opts); 110 | iterations = info.Iterations; 111 | end -------------------------------------------------------------------------------- /codes/appendix B/cplexOptimizer.m: -------------------------------------------------------------------------------- 1 | function [xsol, fval, exitflag, iterations] = ... 2 | cplexOptimizer(mpsFullPath, algorithm, ... 3 | simplexTol, barrierTol, maxTime, simplexMaxIter, ... 4 | barrierMaxIter, parallelMode, presolve, ... 5 | numPresolvePasses, factorFreq) 6 | % Filename: cplexOptimizer.m 7 | % Description: the function is a MATLAB code to solve LPs 8 | % using CPLEX 9 | % Authors: Ploskas, N., & Samaras, N. 10 | % 11 | % Syntax: [xsol, fval, exitflag, iterations] = ... 12 | % cplexOptimizer(mpsFullPath, algorithm, ... 13 | % simplexTol, barrierTol, maxTime, simplexMaxIter, ... 14 | % barrierMaxIter, parallelMode, presolve, ... 15 | % numPresolvePasses, factorFreq) 16 | % 17 | % Input: 18 | % -- mpsFullPath: the full path of the MPS file 19 | % -- algorithm: the CPLEX algorithm that will be used 20 | % (optional, possible values: 0 - automatic, 1 - 21 | % primal simplex, 2 - dual simplex, 3 - network 22 | % simplex, 4 - barrier, 5 - sifting, 6 - concurrent 23 | % optimizers) 24 | % -- simplexTol: the tolerance for simplex type 25 | % algorithms (optional) 26 | % -- barrierTol: the tolerance for the barrier 27 | % algorithm (optional) 28 | % -- maxTime: the maximum execution time in seconds 29 | % -- (optional) 30 | % -- simplexMaxIter: the maximum number of iterations 31 | % -- for simplex type algorithms (optional) 32 | % -- barrierMaxIter: the maximum number of iterations 33 | % -- for the barrier algorithm (optional) 34 | % -- parallelModel: the parallel model (optional, 35 | % possible values: -1: opportunistic, 0: automatic, 36 | % 1: deterministic) 37 | % -- presolve: decides whether CPLEX applies presolve 38 | % (optional, possible values: 0: no, 1: yes) 39 | % -- numPresolvePasses: the number of presolver passes 40 | % (optional) 41 | % -- factorFreq: every factorFreq number of iterations, 42 | % the basis inverse is re-computed from scratch 43 | % (optional) 44 | % 45 | % Output: 46 | % -- xsol: the solution found by the solver (size m x 1) 47 | % -- fval: the value of the objective function at the 48 | % solution xsol 49 | % -- exitflag: the reason that the algorithm terminated 50 | % (1: the solver converged to a solution x, 2: the 51 | % LP problem is unbounded, 3: the LP problem is 52 | % infeasible, 10: the number of iterations exceeded 53 | % the maxIter option, 11: time reached) 54 | % -- iterations: the number of iterations 55 | 56 | % set user defined values to options 57 | cplex = Cplex; 58 | if exist('algorithm') 59 | cplex.Param.lpmethod.Cur = algorithm; 60 | end 61 | if exist('simplexTol') 62 | cplex.Param.simplex.tolerances.optimality.Cur ... 63 | = simplexTol; 64 | end 65 | if exist('barrierTol') 66 | cplex.Param.barrier.convergetol.Cur = barrierTol; 67 | end 68 | if exist('maxTime') 69 | cplex.Param.timelimit.Cur = maxTime; 70 | end 71 | if exist('simplexMaxIter') 72 | cplex.Param.simplex.limits.iterations.Cur = ... 73 | simplexMaxIter; 74 | end 75 | if exist('barrierMaxIter') 76 | cplex.Param.barrier.limits.iteration.Cur = ... 77 | barrierMaxIter; 78 | end 79 | if exist('parallelMode') 80 | cplex.Param.parallel.Cur = parallelMode; 81 | end 82 | if exist('presolve') 83 | cplex.Param.preprocessing.presolve.Cur = ... 84 | presolve; 85 | end 86 | if exist('numPresolvePasses') 87 | cplex.Param.preprocessing.numpass.Cur = ... 88 | numPresolvePasses; 89 | end 90 | if exist('factorFreq') 91 | cplex.Param.simplex.refactor.Cur = factorFreq; 92 | end 93 | cplex.DisplayFunc = []; 94 | % read the MPS file 95 | cplex.readModel(mpsFullPath); 96 | % call CPLEX solver 97 | cplex.solve; 98 | % export solution 99 | xsol = cplex.Solution.x; 100 | fval = cplex.Solution.objval; 101 | exitflag = cplex.Solution.status; 102 | if isfield(cplex.Solution, 'itcnt') 103 | iterations = cplex.Solution.itcnt; 104 | else 105 | iterations = cplex.Solution.baritcnt; 106 | end 107 | end -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/beaconfd.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/beaconfd.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/cari.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/cari.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/farm.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/farm.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/itest6.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/itest6.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/klein2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/klein2.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/nsic1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/nsic1.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/nsic2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/nsic2.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/osa-07.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/osa-07.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/osa-14.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/osa-14.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/osa-30.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/osa-30.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/rosen1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/rosen1.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/rosen10.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/rosen10.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/rosen2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/rosen2.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/rosen7.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/rosen7.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/rosen8.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/rosen8.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/sc205.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/sc205.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/scfxm1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/scfxm1.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/sctap2.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/sctap2.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MAT/sctap3.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/benchmarkLPs/MAT/sctap3.mat -------------------------------------------------------------------------------- /codes/benchmarkLPs/MPS/farm.mps: -------------------------------------------------------------------------------- 1 | NAME LINDO GENERATED MPS FILE( MAX) 2 | ROWS 3 | N 1 4 | L R1 5 | L R2 6 | L R3 7 | E R4 8 | E R5 9 | L R6 10 | L R7 11 | COLUMNS 12 | X11 1 346. R1 4. 13 | X11 R2 1. R3 20. 14 | X12 1 346. R1 4. 15 | X12 R2 1. R3 15. 16 | X12 R4 40. 17 | X21 1 248. R1 2. 18 | X21 R2 1. 19 | X22 1 248. R1 2. 20 | X22 R2 1. R4 35. 21 | X31 1 399. R1 1. 22 | X31 R2 1. R5 1. 23 | X32 1 399. R1 1. 24 | X32 R2 1. R4 50. 25 | Y11 1 200. R1 250. 26 | Y11 R2 2. R3 30. 27 | Y11 R6 1. 28 | Y12 1 200. R1 250. 29 | Y12 R2 2. R4 15. 30 | Y12 R6 1. 31 | Y21 1 75. R1 125. 32 | Y21 R2 1. R3 20. 33 | Y21 R7 1. 34 | Y22 1 75. R1 125. 35 | Y22 R2 1. R4 10. 36 | Y22 R7 1. 37 | Z1 1 2.35 R3 1. 38 | Z2 1 3.5 R4 1. 39 | RHS 40 | RHS R1 25000. R2 300. 41 | RHS R3 1500. R4 5000. 42 | RHS R6 50. R7 100. 43 | ENDATA 44 | -------------------------------------------------------------------------------- /codes/benchmarkLPs/MPS/itest6.mps: -------------------------------------------------------------------------------- 1 | NAME ITEST6 2 | ROWS 3 | L ROW1 4 | L ROW2 5 | L ROW3 6 | G ROW4 7 | G ROW5 8 | L ROW6 9 | G ROW7 10 | L ROW8 11 | E ROW9 12 | E ROW10 13 | G ROW11 14 | N OBJ10 15 | COLUMNS 16 | X1 ROW2 1. 17 | X2 ROW4 -1. ROW5 -1. 18 | X2 ROW9 1. ROW10 1. 19 | X2 ROW11 1. OBJ10 1. 20 | X3 ROW1 .8 ROW4 1. 21 | X3 ROW6 1. ROW9 -.05 22 | X3 ROW10 -.04 OBJ10 1. 23 | X4 ROW1 1. ROW5 1. 24 | X4 ROW10 -.05 OBJ10 1. 25 | X5 ROW7 -3. ROW8 .5 26 | X6 ROW3 2. ROW8 .6 27 | X7 ROW7 1. 28 | X8 ROW3 -1. 29 | RHS 30 | RHS1 ROW1 10000. ROW2 90000. 31 | RHS1 ROW3 10000. ROW4 50000. 32 | RHS1 ROW5 87000. ROW6 50000. 33 | RHS1 ROW7 10000. ROW8 300000. 34 | RHS1 ROW9 5000. ROW10 4500. 35 | RHS1 ROW11 80000. 36 | ENDATA 37 | -------------------------------------------------------------------------------- /codes/chapter10/lprref.m: -------------------------------------------------------------------------------- 1 | function [AEqin, bEqin, jb, out, rowindex, ... 2 | infeasible] = lprref(A, b, Eqin, tol) 3 | % Filename: lprref.m 4 | % Description: the function calculates a row echelon 5 | % form of matrix A for LPs using Gauss-Jordan 6 | % elimination with partial pivoting 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [AEqin, bEqin, jb, out, rowindex, ... 10 | % infeasible] = lprref(A, b, Eqin, tol) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % -- Eqin: vector of the type of the constraints 18 | % (size m x 1) 19 | % -- tol: tolerance 20 | % 21 | % Output: 22 | % -- AEqin: reduced row echelon form of A (size m x n) 23 | % -- bEqin: reduced vector b (size m x 1) 24 | % -- jb: basis of matrix A (size m x m) 25 | % -- rowindex: a matrix with the row redundant indices 26 | % (size 2 x m) 27 | % -- infeasible: if the problem is infeasible or not 28 | 29 | % initialize output variables 30 | infeasible = 0; 31 | out = []; 32 | % find all equality constraints 33 | a0 = find(Eqin == 0); 34 | AEqin = A(a0, :); 35 | bEqin = b(a0, :); 36 | [m, n] = size(AEqin); 37 | rowindex = zeros(2, m); 38 | rowindex(1, 1:m) = a0'; 39 | if nargin < 4 % compute tol, if it was not given as input 40 | tol = max(m, n) * eps * norm(A, 'inf'); 41 | end 42 | i = 1; 43 | j = 1; 44 | jb = []; 45 | % apply Gauss-Jordan elimination with partial pivoting 46 | while (i <= m) && (j <= n) 47 | [p, k] = max(abs(AEqin(i:m, j))); 48 | if p < tol 49 | AEqin(i:m, j) = zeros(m - i + 1, 1); 50 | j = j + 1; 51 | elseif p ~= 0 52 | k = k + i - 1; 53 | jb = [jb j]; 54 | AEqin([i k], :) = AEqin([k i], :); 55 | bEqin([i k], :) = bEqin([k i], :); 56 | rowindex(:, [i k]) = rowindex(:, [k i]); 57 | bEqin(i, :) = bEqin(i, :) / AEqin(i, j); 58 | AEqin(i, j:n) = AEqin(i, j:n) / AEqin(i, j); 59 | i_nz = find(AEqin(:, j)); 60 | i_nz = setdiff(i_nz, i); 61 | for t = i_nz 62 | if bEqin(i) ~= 0 63 | bEqin(t) = bEqin(t) - AEqin(t, j) * bEqin(i); 64 | toler = abs(bEqin) <= tol; 65 | bEqin(toler == 1) = 0; 66 | end 67 | AEqin(t, j:n) = AEqin(t, j:n) - ... 68 | AEqin(t, j) * AEqin(i, j:n); 69 | toler = abs(AEqin) <= tol; 70 | AEqin(toler == 1) = 0; 71 | end 72 | i = i + 1; 73 | j = j + 1; 74 | end 75 | end 76 | % check for redundant and infeasible constraints 77 | i = 1; 78 | for h = [1:i - 1 i + 1:m] 79 | % redundant constraint 80 | if (AEqin(h, :) == 0) & (bEqin(h) == 0) 81 | rowindex(2, h) = 1; 82 | end 83 | % infeasible constraint 84 | if (AEqin(h,:) == 0) & (bEqin(h) ~= 0) 85 | infeasible = 1; 86 | return; 87 | end 88 | end 89 | % find the indices of the redundant constraints 90 | if any(rowindex(2, :) == 1) 91 | y = find(rowindex(2, :) == 1); 92 | out = y; 93 | end 94 | end -------------------------------------------------------------------------------- /codes/chapter11/ipdipm.m: -------------------------------------------------------------------------------- 1 | function [xsol, fval, exitflag, iterations] = ... 2 | ipdipm(A, c, b, Eqin, MinMaxLP, c0, ... 3 | maxIterations, tol, etaMin, scalingTechnique) 4 | % Filename: ipdipm.m 5 | % Description: the function is an implementation of 6 | % Mehrotra's Predictor-Corrector infeasible 7 | % primal-dual interior point method 8 | % Authors: Ploskas, N., & Samaras, N. 9 | % 10 | % Syntax: [xsol, fval, exitflag, iterations] = ... 11 | % ipdipm(A, c, b, Eqin, MinMaxLP, c0, ... 12 | % maxIterations, tol, etaMin, scalingTechnique) 13 | % 14 | % Input: 15 | % -- A: matrix of coefficients of the constraints 16 | % (size m x n) 17 | % -- c: vector of coefficients of the objective function 18 | % (size n x 1) 19 | % -- b: vector of the right-hand side of the constraints 20 | % (size m x 1) 21 | % -- Eqin: vector of the type of the constraints 22 | % (size m x 1) 23 | % -- MinMaxLP: the type of optimization (optional: 24 | % default value -1 - minimization) 25 | % -- c0: constant term of the objective function 26 | % (optional: default value 0) 27 | % -- maxIterations: maximum number of iterations to 28 | % perform if an optimal solution is not found 29 | % (optional: default value 100) 30 | % -- tole: tolerance for the termination criterion 31 | % (optional: default value 1e-08) 32 | % -- etaMin: parameter eta (optional: default 33 | % value 0.995) 34 | % -- scalingTechnique: the scaling method to be used 35 | % (0: no scaling, 1: arithmetic mean, 2: de Buchet for 36 | % the case p = 1, 3: de Buchet for the case p = 2, 37 | % 4: de Buchet for the case p = Inf, 5: entropy, 38 | % 6: equilibration, 7: geometric mean, 8: IBM MPSX, 39 | % 9: LP-norm for the case p = 1, 10: LP-norm for 40 | % the case p = 2, 11: LP-norm for the case p = Inf) 41 | % (optional: default value 6) 42 | % 43 | % Output: 44 | % -- xsol: the solution found (size n x 1) 45 | % -- fval: the value of the objective function at the 46 | % solution x 47 | % -- exitflag: the reason that the algorithm terminated 48 | % (0: optimal solution found, 1: the LP problem is 49 | % infeasible, -1: the input data is not logically 50 | % or numerically correct) 51 | % -- iterations: the number of iterations 52 | 53 | % initialize output variables 54 | xsol = []; 55 | fval = 0; 56 | exitflag = 0; 57 | iterations = 0; 58 | % set default values to missing inputs 59 | if ~exist('maxIterations') 60 | maxIterations = 100; 61 | end 62 | if ~exist('tol') 63 | tol = 1e-8; 64 | end 65 | if ~exist('etaMin') 66 | etaMin = 0.995; 67 | end 68 | if ~exist('scalingTechnique') 69 | scalingTechnique = 6; 70 | end 71 | [m, n] = size(A); % find the size of matrix A 72 | [m2, n2] = size(c); % find the size of vector c 73 | [m3, n3] = size(Eqin); % find the size of vector Eqin 74 | [m4, n4] = size(b); % find the size of vector b 75 | % check if input data is logically correct 76 | if n2 ~= 1 77 | disp('Vector c is not a column vector.') 78 | exitflag = -1; 79 | return 80 | end 81 | if n ~= m2 82 | disp(['The number of columns in matrix A and ' ... 83 | 'the number of rows in vector c do not match.']) 84 | exitflag = -1; 85 | return 86 | end 87 | if m4 ~= m 88 | disp(['The number of the right-hand side values ' ... 89 | 'is not equal to the number of constraints.']) 90 | exitflag = -1; 91 | return 92 | end 93 | if n3 ~= 1 94 | disp('Vector Eqin is not a column vector') 95 | exitflag = -1; 96 | return 97 | end 98 | if n4 ~= 1 99 | disp('Vector b is not a column vector') 100 | exitflag = -1; 101 | return 102 | end 103 | if m4 ~= m3 104 | disp('The size of vectors Eqin and b does not match') 105 | exitflag = -1; 106 | return 107 | end 108 | % if the type of optimization is maximization, then multiply 109 | % vector c and constant c0 by -1 110 | if MinMaxLP == 1 111 | c = -c; 112 | c0 = -c0; 113 | end 114 | % perform the presolve analysis 115 | disp('---- P R E S O L V E A N A L Y S I S ----') 116 | [A, c, b, Eqin, c0, infeasible, unbounded] = ... 117 | presolve(A, c, b, Eqin, c0); 118 | if infeasible == 1 % the LP problem is infeasible 119 | disp('The LP problem is infeasible') 120 | exitflag = 1; 121 | return 122 | end 123 | if unbounded == 1 % the LP problem is unbounded 124 | disp('The LP problem is unbounded') 125 | exitflag = 2; 126 | return 127 | end 128 | [m, n] = size(A); % find the new size of matrix A 129 | [m2, ~] = size(c); % find the new size of vector c 130 | [m3, ~] = size(Eqin); % find the size of vector Eqin 131 | % scale the LP problem using the selected scaling 132 | % technique 133 | disp('---- S C A L I N G ----') 134 | if scalingTechnique == 1 % arithmetic mean 135 | [A, c, b, ~, ~] = arithmeticMean(A, c, b); 136 | % de buchet for the case p = 1 137 | elseif scalingTechnique == 2 138 | [A, c, b, ~, ~] = debuchet1(A, c, b); 139 | % de buchet for the case p = 2 140 | elseif scalingTechnique == 3 141 | [A, c, b, ~, ~] = debuchet2(A, c, b); 142 | % de buchet for the case p = Inf 143 | elseif scalingTechnique == 4 144 | [A, c, b, ~, ~] = debuchetinf(A, c, b); 145 | elseif scalingTechnique == 5 % entropy 146 | [A, c, b, ~, ~] = entropy(A, c, b); 147 | elseif scalingTechnique == 6 % equilibration 148 | [A, c, b, ~, ~] = equilibration(A, c, b); 149 | elseif scalingTechnique == 7 % geometric mean 150 | [A, c, b, ~, ~] = geometricMean(A, c, b); 151 | elseif scalingTechnique == 8 % IBM MPSX 152 | [A, c, b, ~, ~, ~, ~] = ibmmpsx(A, c, b); 153 | % LP-norm for the case p = 1 154 | elseif scalingTechnique == 9 155 | [A, c, b, ~, ~] = lpnorm1(A, c, b); 156 | % LP-norm for the case p = 2 157 | elseif scalingTechnique == 10 158 | [A, c, b, ~, ~] = lpnorm2(A, c, b); 159 | % LP-norm for the case p = Inf 160 | elseif scalingTechnique == 11 161 | [A, c, b, ~, ~] = lpnorminf(A, c, b); 162 | end 163 | flag = isequal(Eqin, zeros(m3, 1)); 164 | if flag ~= 1 165 | % some or all constraints are inequalities 166 | % add slack variables 167 | axm = nnz(Eqin); 168 | c(m2 + 1:m2 + axm, :) = 0; 169 | A(:, n + 1:n + axm) = zeros(m, axm); 170 | curcol = 1; 171 | for i = 1:m3 172 | % 'greater than or equal to' inequality constraint 173 | if Eqin(i, 1) == 1 174 | A(i, n + curcol) = -1; 175 | curcol = curcol + 1; 176 | % 'less than or equal to' inequality constraint 177 | elseif Eqin(i, 1) == -1 178 | A(i, n + curcol) = 1; 179 | curcol = curcol + 1; 180 | % unrecognized type of constraint 181 | elseif Eqin(i,1) ~= 0 182 | disp('Vector Eqin is not numerically correct.') 183 | exitflag = -1; 184 | return 185 | end 186 | end 187 | end 188 | [m, n] = size(A); % new size of matrix A 189 | % calculate the density of matrix A 190 | density = (nnz(A) / (m * n)) * 100; 191 | % if the density of matrix A is less than 20%, then 192 | % use sparse algebra for faster computations 193 | if density < 20 194 | A = sparse(A); 195 | c = sparse(c); 196 | b = sparse(b); 197 | end 198 | % tolerance for detecting infeasible LPs 199 | infTole = 1.e15 * max([normest(A), normest(b), ... 200 | normest(c)]); 201 | % calculate the starting point using Mehrotra's 202 | % heuristic 203 | x = A' * ((A * A') \ b); 204 | w = (A * A') \ (A * c); 205 | s = c - A' * w; 206 | delta_x = max(-1.5 * min(x), 0); 207 | delta_s = max(-1.5 * min(s), 0); 208 | e = ones(n, 1); 209 | delta_x_s = 0.5 * (x + delta_x * e)' * ... 210 | (s + delta_s * e); 211 | delta_x_c = delta_x + delta_x_s / ... 212 | (sum(s) + n * delta_s); 213 | delta_s_c = delta_s + delta_x_s / ... 214 | (sum(x) + n * delta_x); 215 | x = x + delta_x_c * e; 216 | s = s + delta_s_c * e; 217 | % iterate until maxIterations or the LP problem is 218 | % optimal or infeasible 219 | for i = 1:maxIterations 220 | iterations = iterations + 1; 221 | % calculate the residuals and the duality measure 222 | rd = A' * w + s - c; % dual residual 223 | rp = A * x - b; % primal residual 224 | rc = x .* s; % complementarity residual 225 | mu = x' * s / n; % duality measure 226 | residual = normest(rc, 1) / (1 + abs(b' * w)); 227 | % heuristic to detect infeasible LPs 228 | if isnan(residual) || normest(x) + normest(s) ... 229 | >= infTole 230 | disp('The LP problem is infeasible!'); 231 | exitflag = 1; 232 | break; 233 | end 234 | % the termination criterion 235 | if max(mu, max(normest(rp), normest(rd))) <= tol 236 | xsol = x; 237 | fval = c' * x; % calculate the objective function value 238 | if MinMaxLP == 1 % maximization 239 | fval = full(-(fval + c0)); 240 | else % minimization 241 | fval = full(fval + c0); 242 | end 243 | exitflag = 0; 244 | disp('The LP problem is optimal') 245 | break; 246 | end 247 | % formulate the coefficient matrix of the 248 | % linear systems 249 | M = A * diag(x ./ s) * A'; 250 | [R, p] = chol(M); % factorize M 251 | if p > 0 % if matrix M is positive definite, we 252 | % assume that the LP problem is optimal 253 | xsol = x; 254 | fval = c' * x; % calculate the objective function value 255 | if MinMaxLP == 1 % maximization 256 | fval = full(-(fval + c0)); 257 | else % minimization 258 | fval = full(fval + c0); 259 | end 260 | exitflag = 0; 261 | disp('The LP problem is optimal') 262 | break; 263 | end 264 | % predictor step 265 | rhs = rp - A * ((rc - x .* rd) ./ s); 266 | dw = R \ (R' \ rhs); 267 | ds = rd - A' * dw; 268 | dx = (rc - x .* ds) ./ s; 269 | alpha_p = 1 / max([1; dx ./ x]); 270 | alpha_d = 1 / max([1; ds ./ s]); 271 | % centering parameter step 272 | mun = ((x - alpha_p * dx)' * (s - alpha_d * ds)) / n; 273 | sigma = (mun / mu) ^ 3; 274 | % corrector step 275 | rc = rc - sigma * mu + dx .* ds; 276 | rhs = rp - A * ((rc - x .* rd) ./ s); 277 | dw = R \ (R' \ rhs); 278 | ds = rd - A' * dw; 279 | dx = (rc - x .* ds) ./ s; 280 | eta = max(etaMin, 1 - mu); 281 | alpha_p = eta / max([eta; dx ./ x]); 282 | alpha_d = eta / max([eta; ds ./ s]); 283 | % update step 284 | x = x - alpha_p * dx; 285 | w = w - alpha_d * dw; 286 | s = s - alpha_d * ds; 287 | % print intermediate results every 5 iterations 288 | if mod(iterations, 5) == 0 289 | % calculate the value of the objective 290 | % function 291 | if MinMaxLP == 1 % maximization 292 | fval = full(-(c' * x + c0)); 293 | else % minimization 294 | fval = full(c' *x + c0); 295 | end 296 | fprintf(['Iteration %i - objective value: ' ... 297 | '%f\n'], iterations, fval); 298 | end 299 | end 300 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysis.m: -------------------------------------------------------------------------------- 1 | function [cBounds, bBounds, sp, rc] = ... 2 | sensitivityAnalysis(A, c, b, Eqin, MinMaxLP, BasicList) 3 | % Filename: sensitivityAnalysis.m 4 | % Description: the function is an implementation of the 5 | % sensitivity analysis 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [cBounds, bBounds, sp, rc] = ... 9 | % sensitivityAnalysis(A, c, b, Eqin, MinMaxLP, BasicList) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % -- Eqin: vector of the type of the constraints 19 | % (size m x 1) 20 | % -- MinMaxLP: the type of optimization (optional: 21 | % default value -1 - minimization) 22 | % -- BasicList: vector of the indices of the basic 23 | % variables (size 1 x m) 24 | % 25 | % Output: 26 | % -- cBounds: matrix of the range of the coefficients 27 | % of the objective function (size 2 x n) 28 | % -- bBounds: matrix of the range of the right-hand 29 | % side coefficients (size 2 x m) 30 | % -- sp: vector of the shadow prices (size 1 x m) 31 | % -- rc: vector of the reduced costs (size 1 x n) 32 | 33 | % transform the LP problem in its standard form 34 | [A, c, b, Eqin, MinMaxLP] = ... 35 | general2standard(A, c, b, Eqin, MinMaxLP); 36 | % find the ranges of the coefficients of the 37 | % objective function 38 | [cl, cu] = sensitivityAnalysisc(A, c, BasicList); 39 | cBounds = [cl; cu]; 40 | % find the ranges of the right-hand side 41 | % coefficients 42 | [bl, bu] = sensitivityAnalysisb(A, b, BasicList); 43 | bBounds = [bl; bu]; 44 | % calculate the shadow prices and reduced costs 45 | BasisInv = inv(A(:, BasicList)); % invert the basis 46 | % calculate the reduced costs 47 | sp = c(BasicList)' * BasisInv; 48 | % calculate the shadow prices 49 | rc = c' - sp * A; 50 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisAddConstraint.m: -------------------------------------------------------------------------------- 1 | function [optimal] = ... 2 | sensitivityAnalysisAddConstraint(A, c, b, ... 3 | BasicList, Amplus1, bmplus1, constrEqin) 4 | % Filename: sensitivityAnalysisAddConstraint.m 5 | % Description: the function is an implementation of the 6 | % sensitivity analysis when adding a new constraint 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [optimal] = ... 10 | % sensitivityAnalysisAddConstraint(A, c, b, ... 11 | % BasicList, Amplus1, bmplus1, constrEqin) 12 | % 13 | % Input: 14 | % -- A: matrix of coefficients of the constraints 15 | % (size m x n) 16 | % -- c: vector of coefficients of the objective function 17 | % (size n x 1) 18 | % -- b: vector of the right-hand side of the constraints 19 | % (size m x 1) 20 | % -- BasicList: vector of the indices of the basic 21 | % variables (size 1 x m) 22 | % -- Amplus1: the new row in the matrix of coefficients 23 | % of the constraints (size 1 x n) 24 | % -- bmplus1: the right-hand side value of the new 25 | % constraint 26 | % -- constrEqin: the type of the new constraint (-1: 27 | % constraint type is 'less than or equal to', 0: 28 | % equality constraint, 1: constraint type is 29 | % 'greater than or equal to') 30 | % 31 | % Output: 32 | % -- optimal: a flag variable showing if the LP problem 33 | % remains optimal or not (0 - the current basis is 34 | % not optimal, 1 - the current basis remains 35 | % optimal) 36 | 37 | [m, n] = size(A); % the size of matrix A 38 | % calculate the basis inverse 39 | BasisInv = inv(A(:, BasicList)); 40 | % compute vector x 41 | x = zeros(1, n); 42 | x(BasicList) = BasisInv * b; 43 | % calculate vectors w and s 44 | w = c(BasicList)' * BasisInv; 45 | s = c' - w * A; 46 | % check if the current basis is not optimal 47 | if any(x(BasicList) < 0) 48 | disp('The current basis is not optimal!') 49 | optimal = 0; 50 | return 51 | end 52 | if any(s < 0) 53 | disp('The current basis is not optimal!') 54 | optimal = 0; 55 | return 56 | end 57 | % add the new constraint 58 | b = [b; bmplus1]; 59 | c = [c; 0]; 60 | if constrEqin == -1 % 'less than or equal to' constraint 61 | A = [A zeros(m, 1); Amplus1 1]; 62 | elseif constrEqin == 0 % equality constraint 63 | % we do not need to add a new variable, but 64 | % we add a new variable for simplicity's sake 65 | A = [A zeros(m, 1); Amplus1 0]; 66 | % 'greater than or equal to' constraint 67 | elseif constrEqin == 1 68 | A = [A zeros(m, 1); Amplus1 -1]; 69 | end 70 | % add the new constraint to the basic list 71 | BasicList = [BasicList n + 1]; 72 | % calculate the new basis inverse 73 | BasisInv = inv(A(:, BasicList)); 74 | % compute the new vector x 75 | x = zeros(1, n + 1); 76 | x(BasicList) = BasisInv * b; 77 | % check if the current basis is not optimal 78 | if x(n + 1) >= 0 79 | disp('The current basis remains optimal!') 80 | optimal = 1; 81 | return 82 | else 83 | disp('The current basis is not optimal!') 84 | optimal = 0; 85 | end 86 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisAddVariable.m: -------------------------------------------------------------------------------- 1 | function [optimal] = ... 2 | sensitivityAnalysisAddVariable(A, c, b, ... 3 | BasicList, Anplus1, cnplus1) 4 | % Filename: sensitivityAnalysisAddVariable.m 5 | % Description: the function is an implementation of the 6 | % sensitivity analysis when adding a new variable 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [optimal] = ... 10 | % sensitivityAnalysisAddVariable(A, c, b, ... 11 | % BasicList, Anplus1, cnplus1) 12 | % 13 | % Input: 14 | % -- A: matrix of coefficients of the constraints 15 | % (size m x n) 16 | % -- c: vector of coefficients of the objective function 17 | % (size n x 1) 18 | % -- b: vector of the right-hand side of the constraints 19 | % (size m x 1) 20 | % -- BasicList: vector of the indices of the basic 21 | % variables (size 1 x m) 22 | % -- Anplus1: the new column in the matrix of coefficients 23 | % of the constraints (size m x 1) 24 | % -- cnplus1: the cost coefficient of the new variable 25 | % 26 | % Output: 27 | % -- optimal: a flag variable showing if the LP problem 28 | % remains optimal or not (0 - the current basis is 29 | % not optimal, 1 - the current basis remains 30 | % optimal) 31 | 32 | [~, n] = size(A); % the size of matrix A 33 | % calculate the basis inverse 34 | BasisInv = inv(A(:, BasicList)); 35 | % compute vector x 36 | x = zeros(1, n); 37 | x(BasicList) = BasisInv * b; 38 | % calculate vectors w and s 39 | w = c(BasicList)' * BasisInv; 40 | s = c' - w * A; 41 | % check if the current basis is not optimal 42 | if any(x(BasicList) < 0) 43 | disp('The current basis is not optimal!') 44 | optimal = 0; 45 | return 46 | end 47 | if any(s < 0) 48 | disp('The current basis is not optimal!') 49 | optimal = 0; 50 | return 51 | end 52 | % find the value of the new reduced cost 53 | Snplus1 = cnplus1 - w * Anplus1; 54 | % check if the current basis remains optimal 55 | if Snplus1 >= 0 56 | disp('The current basis remains optimal!') 57 | optimal = 1; 58 | return 59 | else 60 | disp('The current basis is not optimal!') 61 | optimal = 0; 62 | return 63 | end 64 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisChangeb.m: -------------------------------------------------------------------------------- 1 | function [optimal] = sensitivityAnalysisChangeb(A, ... 2 | c, b, BasicList, index, DeltaB) 3 | % Filename: sensitivityAnalysisChangeb.m 4 | % Description: the function is an implementation of the 5 | % sensitivity analysis when a change in the right-hand 6 | % side occurs 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [optimal] = sensitivityAnalysisChangeb(A, ... 10 | % c, b, BasicList, index, DeltaB) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- BasicList: vector of the indices of the basic 20 | % variables (size 1 x m) 21 | % -- index: the index of the constraint where the change 22 | % in the right-hand side occurs 23 | % -- DeltaB: the amount of change in the right-hand side 24 | % 25 | % Output: 26 | % -- optimal: a flag variable showing if the LP problem 27 | % remains optimal or not (0 - the current basis is 28 | % not optimal, 1 - the current basis remains 29 | % optimal) 30 | 31 | [~, n] = size(A); % the size of matrix A 32 | % calculate the basis inverse 33 | BasisInv = inv(A(:, BasicList)); 34 | % compute vector x 35 | x = zeros(1, n); 36 | x(BasicList) = BasisInv * b; 37 | % calculate vectors w and s 38 | w = c(BasicList)' * BasisInv; 39 | s = c' - w * A; 40 | % check if the current basis is not optimal 41 | if any(x(BasicList) < 0) 42 | disp('The current basis is not optimal!') 43 | optimal = 0; 44 | return 45 | end 46 | if any(s < 0) 47 | disp('The current basis is not optimal!') 48 | optimal = 0; 49 | return 50 | end 51 | % find the ranges of the right-hand side coefficients 52 | [bl, bu] = sensitivityAnalysisb(A, b, BasicList); 53 | % change the right-hand side of the specific constraint 54 | b(index) = b(index) + DeltaB; 55 | % check if the current basis remains optimal 56 | if b(index) >= bl(index) && b(index) <= bu(index) 57 | disp('The current basis remains optimal!') 58 | optimal = 1; 59 | return 60 | else 61 | disp('The current basis is not optimal!') 62 | optimal = 0; 63 | return 64 | end 65 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisChangec.m: -------------------------------------------------------------------------------- 1 | function [optimal] = sensitivityAnalysisChangec(A, ... 2 | c, b, MinMaxLP, BasicList, index, DeltaC) 3 | % Filename: sensitivityAnalysisChangec.m 4 | % Description: the function is an implementation of the 5 | % sensitivity analysis when a change in the cost 6 | % coefficients occurs 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [optimal] = sensitivityAnalysisChangec(A, ... 10 | % c, b, MinMaxLP, BasicList, index, DeltaC) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- MinMaxLP: the type of optimization (optional: 20 | % default value -1 - minimization) 21 | % -- BasicList: vector of the indices of the basic 22 | % variables (size 1 x m) 23 | % -- index: the index of the variable where the change 24 | % in the cost coefficients occurs 25 | % -- DeltaC: the amount of change in the cost vector 26 | % 27 | % Output: 28 | % -- optimal: a flag variable showing if the LP problem 29 | % remains optimal or not (0 - the current basis is 30 | % not optimal, 1 - the current basis remains 31 | % optimal) 32 | 33 | [~, n] = size(A); % the size of matrix A 34 | % calculate the basis inverse 35 | BasisInv = inv(A(:, BasicList)); 36 | % compute vector x 37 | x = zeros(1, n); 38 | x(BasicList) = BasisInv * b; 39 | % calculate vectors w and s 40 | w = c(BasicList)' * BasisInv; 41 | s = c' - w * A; 42 | % check if the current basis is not optimal 43 | if any(x(BasicList) < 0) 44 | disp('The current basis is not optimal!') 45 | optimal = 0; 46 | return 47 | end 48 | if any(s < 0) 49 | disp('The current basis is not optimal!') 50 | optimal = 0; 51 | return 52 | end 53 | % find the ranges of the cost coefficients 54 | [cl, cu] = sensitivityAnalysisc(A, c, ... 55 | MinMaxLP, BasicList); 56 | % change the cost coefficient of the variable 57 | % index 58 | c(index) = c(index) + DeltaC; 59 | % check if the current basis remains optimal 60 | if c(index) >= cl(index) && c(index) <= cu(index) 61 | disp('The current basis remains optimal!') 62 | optimal = 1; 63 | return 64 | else 65 | disp('The current basis is not optimal!') 66 | optimal = 0; 67 | return 68 | end 69 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisb.m: -------------------------------------------------------------------------------- 1 | function [bl, bu] = sensitivityAnalysisb(A, b, BasicList) 2 | % Filename: sensitivityAnalysisb.m 3 | % Description: the function is an implementation of the 4 | % sensitivity analysis for the right-hand side 5 | % coefficients 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [bl, bu] = sensitivityAnalysisb(A, b, BasicList) 9 | % 10 | % Input: 11 | % -- A: matrix of coefficients of the constraints 12 | % (size m x n) 13 | % -- b: vector of the right-hand side of the constraints 14 | % (size m x 1) 15 | % -- BasicList: vector of the indices of the basic 16 | % variables (size 1 x m) 17 | % 18 | % Output: 19 | % -- bl: vector of the lower values of the range of the 20 | % right-hand side coefficients (size 1 x m) 21 | % -- bu: vector of the upper values of the range of the 22 | % right-hand side coefficients (size 1 x m) 23 | 24 | m = length(BasicList); % find the number of constraints 25 | % initialize output 26 | bl = zeros(1, m); 27 | bu = zeros(1, m); 28 | BasisInv = inv(A(:, BasicList)); % invert the basis 29 | Xb = BasisInv * b; % compute vector Xb 30 | % calculate the lower and upper values of the range 31 | % of the right-hand side coefficients 32 | for i = 1:m 33 | % find the positive values in the basis inverse 34 | % of the specific constraint 35 | t = find(BasisInv(:, i) > 0); 36 | if isempty(t) % if no positive value exists 37 | bl(i) = -Inf; 38 | else % calculate the lower value 39 | bl(i) = b(i) + max(-Xb(t) ./ BasisInv(t, i)); 40 | end 41 | % find the negative values in the basis inverse 42 | % of the specific constraint 43 | t = find(BasisInv(:, i) < 0); 44 | if isempty(t) % if no negative value exists 45 | bu(i) = Inf; 46 | else % calculate the upper value 47 | bu(i) = b(i) + min(-Xb(t) ./ BasisInv(t, i)); 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /codes/chapter12/sensitivityAnalysisc.m: -------------------------------------------------------------------------------- 1 | function [cl, cu] = sensitivityAnalysisc(A, c, BasicList) 2 | % Filename: sensitivityAnalysisc.m 3 | % Description: the function is an implementation of the 4 | % sensitivity analysis for the coefficients of the 5 | % objective function 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [cl, cu, sp] = sensitivityAnalysisc(A, c, ... 9 | % MinMaxLP, BasicList) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- BasicList: vector of the indices of the basic 17 | % variables (size 1 x m) 18 | % 19 | % Output: 20 | % -- cl: vector of the lower values of the range of the 21 | % coefficients of the objective function (size 1 x n) 22 | % -- cu: vector of the upper values of the range of the 23 | % coefficients of the objective function (size 1 x n) 24 | 25 | n = length(c); % find the number of variables 26 | % initialize output 27 | cl = zeros(1, n); 28 | cu = zeros(1, n); 29 | % find the nonbasic list 30 | NonBasicList = setdiff([1:n], BasicList); 31 | BasisInv = inv(A(:, BasicList)); % invert the basis 32 | w = c(BasicList)' * BasisInv; % calculate the simplex multiplier 33 | % calculate the reduced costs 34 | Sn = c(NonBasicList)' - w * A(:, NonBasicList); 35 | % calculate the lower and upper values of the range 36 | % of the coefficients of the objective function 37 | for j = 1:n 38 | % if it is a nonbasic variable 39 | if ismember(j, NonBasicList) 40 | t = find(NonBasicList == j); 41 | cu(j) = Inf; 42 | cl(j) = c(j) - Sn(t(1)); 43 | else % if it is a basic variable 44 | r = find(BasicList == j); 45 | HrN = BasisInv(r, :) * A(:, NonBasicList); 46 | HrNplus = find(HrN > 0); 47 | HrNminus = find(HrN < 0); 48 | if isempty(HrNplus) 49 | cu(j) = Inf; 50 | else 51 | cu(j) = c(j) + min(Sn(HrNplus) ... 52 | ./ HrN(HrNplus)); 53 | end 54 | if isempty(HrNminus) 55 | cl(j) = -Inf; 56 | else 57 | cl(j) = c(j) + max(Sn(HrNminus) ... 58 | ./ HrN(HrNminus)); 59 | end 60 | end 61 | end 62 | end -------------------------------------------------------------------------------- /codes/chapter2/canonical2standard.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = ... 2 | canonical2standard(A, c, b, Eqin, MinMaxLP) 3 | % Filename: canonical2standard.m 4 | % Description: the function is an implementation of the 5 | % transformation of an LP problem in its canonical form 6 | % to its standard form 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, MinMaxLP] = ... 10 | % canonical2standard(A, c, b, Eqin, MinMaxLP) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- MinMaxLP: the type of optimization 22 | % 23 | % Output: 24 | % -- A: transformed matrix of coefficients of the 25 | % constraints (size m x n) 26 | % -- c: transformed vector of coefficients of the objective 27 | % function (size n x 1) 28 | % -- b: transformed vector of the right-hand side of the 29 | % constraints (size m x 1) 30 | % -- Eqin: transformed vector of the type of the 31 | % constraints (size m x 1) 32 | % -- MinMaxLP: the type of optimization 33 | 34 | [m, n] = size(A); % size of matrix A 35 | % find all constraints that are not equalities 36 | for i = 1:m 37 | % transform constraints in the form 'less than or 38 | % equal to' to equality constraints 39 | if Eqin(i) == -1 40 | A = [A zeros(m, 1)]; 41 | A(i, n + 1) = 1; 42 | c = [c; 0]; 43 | Eqin(i) = 0; 44 | n = n + 1; 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /codes/chapter2/example1.mn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/chapter2/example1.mn -------------------------------------------------------------------------------- /codes/chapter2/example2.mn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/chapter2/example2.mn -------------------------------------------------------------------------------- /codes/chapter2/example3.mn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/codes/chapter2/example3.mn -------------------------------------------------------------------------------- /codes/chapter2/general2canonical.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP, c0] = ... 2 | general2canonical(A, c, b, Eqin, MinMaxLP, c0) 3 | % Filename: general2canonical.m 4 | % Description: the function is an implementation of the 5 | % transformation of a general LP problem to its 6 | % canonical form 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, MinMaxLP, c0] = ... 10 | % general2canonical(A, c, b, Eqin, MinMaxLP, c0) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- MinMaxLP: the type of optimization 22 | % -- c0: constant term of the objective function 23 | % 24 | % Output: 25 | % -- A: transformed matrix of coefficients of the 26 | % constraints (size m x n) 27 | % -- c: transformed vector of coefficients of the objective 28 | % function (size n x 1) 29 | % -- b: transformed vector of the right-hand side of the 30 | % constraints (size m x 1) 31 | % -- Eqin: transformed vector of the type of the 32 | % constraints (size m x 1) 33 | % -- MinMaxLP: the type of optimization 34 | % -- c0: updated constant term of the objective function 35 | 36 | [m, ~] = size(A); % size of matrix A 37 | % if the LP problem is a maximization problem, transform it 38 | % to a minimization problem 39 | if MinMaxLP == 1 40 | MinMaxLP = -1; 41 | c = -c; 42 | end 43 | % find all constraints that are not in the form 'less than 44 | % or equal to' 45 | for i = 1:m 46 | % transform constraints in the form 'greater than or 47 | % equal to' 48 | if Eqin(i) == 1 49 | A(i, :) = -A(i, :); 50 | b(i) = -b(i); 51 | Eqin(i) = -1; 52 | elseif Eqin(i) == 0 % transform equality constraints 53 | f = find(A(i, :) ~= 0); 54 | f = f(1); 55 | b(i) = b(i) / A(i, f); 56 | A(i, :) = A(i, :) / A(i, f); 57 | b([1:i - 1, i + 1:m]) = b([1:i - 1, i + 1:m]) - ... 58 | A([1:i - 1, i + 1:m], f) .* b(i); 59 | A([1:i - 1, i + 1:m], :) = ... 60 | A([1:i - 1, i + 1:m], :) - ... 61 | A([1:i - 1, i + 1:m], f) * A(i, :); 62 | c0 = c0 + c(f) * b(i); 63 | c = c - c(f) * A(i, :); 64 | A(:, f) = []; 65 | c(f) = []; 66 | Eqin(i) = -1; 67 | end 68 | end 69 | end -------------------------------------------------------------------------------- /codes/chapter2/general2standard.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = ... 2 | general2standard(A, c, b, Eqin, MinMaxLP) 3 | % Filename: general2standard.m 4 | % Description: the function is an implementation of the 5 | % transformation of a general LP problem to its 6 | % standard form 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, MinMaxLP] = ... 10 | % general2standard(A, c, b, Eqin, MinMaxLP) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- MinMaxLP: the type of optimization 22 | % 23 | % Output: 24 | % -- A: transformed matrix of coefficients of the 25 | % constraints (size m x n) 26 | % -- c: transformed vector of coefficients of the objective 27 | % function (size n x 1) 28 | % -- b: transformed vector of the right-hand side of the 29 | % constraints (size m x 1) 30 | % -- Eqin: transformed vector of the type of the 31 | % constraints (size m x 1) 32 | % -- MinMaxLP: the type of optimization 33 | 34 | [m, n] = size(A); % size of matrix A 35 | % if the LP problem is a maximization problem, transform it 36 | % to a minimization problem 37 | if MinMaxLP == 1 38 | MinMaxLP = -1; 39 | c = -c; 40 | end 41 | % find all constraints that are not equalities 42 | for i = 1:m 43 | % transform constraints in the form 'less than or 44 | % equal to' to equality constraints 45 | if Eqin(i) == -1 46 | A(i, n + 1) = 1; 47 | Eqin(i) = 0; 48 | c(n + 1) = 0; 49 | n = n + 1; 50 | % transform constraints in the form 'greater than or 51 | % equal to' to equality constraints 52 | elseif Eqin(i) == 1 53 | A(i, n + 1) = -1; 54 | Eqin(i) = 0; 55 | c(n + 1) = 0; 56 | n = n + 1; 57 | end 58 | end 59 | end -------------------------------------------------------------------------------- /codes/chapter2/primal2dual.m: -------------------------------------------------------------------------------- 1 | function [DA, Dc, Db, DEqin, DMinMaxLP, DVarConst] = ... 2 | primal2dual(A, c, b, Eqin, MinMaxLP, VarConst) 3 | % Filename: primal2dual.m 4 | % Description: the function is an implementation of the 5 | % transformation of a primal LP problem to its dual 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [DA, Dc, Db, DEqin, DMinMaxLP, DVarConst] = ... 9 | % primal2dual(A, c, b, Eqin, MinMaxLP, VarConst) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints of the 13 | % primal LP problem (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % of the primal LP problem (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % of the primal LP problem (size m x 1) 18 | % -- Eqin: vector of the type of the constraints of the 19 | % primal LP problem (size m x 1) 20 | % -- MinMaxLP: the type of optimization of the primal 21 | % LP problem 22 | % -- VarConst: vector of the variables' constraints of the 23 | % primal LP problem (0 - free variable, 1 - variable 24 | % <= 0, 2 - variable >= 0) (size n x 1) 25 | % 26 | % Output: 27 | % -- DA: matrix of coefficients of the constraints of the 28 | % dual LP problem (size n x m) 29 | % -- Dc: vector of coefficients of the objective function 30 | % of the dual LP problem (size m x 1) 31 | % -- Db: vector of the right-hand side of the constraints 32 | % of the dual LP problem (size n x 1) 33 | % -- DEqin: vector of the type of the constraints of the 34 | % dual LP problem (size n x 1) 35 | % -- DMinMaxLP: the type of optimization of the dual 36 | % LP problem 37 | % -- DVarConst: vector of the variables' constraints of the 38 | % dual LP problem (0 - free variable, 1 - variable 39 | % <= 0, 2 - variable >= 0) (size m x 1) 40 | 41 | % if the primal is a minimization problem, then the 42 | % dual is a maximization one and vice versa 43 | DMinMaxLP = -MinMaxLP; 44 | % the coefficients of the objective function of the 45 | % dual LP problem are the right-hand side values of 46 | % the primal LP problem 47 | Dc = b; 48 | % the right-hand side values of the dual LP problem 49 | % are the coefficients of the objective function of the 50 | % primal LP problem 51 | Db = c; 52 | % the coefficient matrix of the dual LP problem is the 53 | % transpose of the coefficient matrix of the primal LP 54 | % problem 55 | DA = A'; 56 | [m, n] = size(A); % size of matrix A 57 | % calculate the vector of the type of the constraints 58 | DEqin = zeros(n, 1); 59 | for i = 1:n 60 | % free variable -> equality constraint 61 | if VarConst(i) == 0 62 | DEqin(i) = 0; 63 | % variable <= 0 -> 'greater than or equal to' 64 | % constraint 65 | elseif VarConst(i) == 1 66 | DEqin(i) = 1; 67 | % variable >= 0 -> 'less than or equal to' 68 | % constraint 69 | elseif VarConst(i) == 2 70 | DEqin(i) = -1; 71 | end 72 | end 73 | % calculate the vector of variables' constraints 74 | DVarConst = zeros(m, 1); 75 | for j = 1:m 76 | % equality constraint -> free variable 77 | if Eqin(j) == 0 78 | DVarConst(j) = 0; 79 | % 'less than or equal to' constraint -> 80 | % variable <= 0 81 | elseif Eqin(j) == -1 82 | DVarConst(j) = 1; 83 | % 'greater than or equal to' constraint -> 84 | % variable >= 0 85 | elseif Eqin(j) == 1 86 | DVarConst(j) = 2; 87 | end 88 | end 89 | end -------------------------------------------------------------------------------- /codes/chapter2/standard2canonical.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = ... 2 | standard2canonical(A, c, b, Eqin, MinMaxLP) 3 | % Filename: standard2canonical.m 4 | % Description: the function is an implementation of the 5 | % transformation of an LP problem in its standard form 6 | % to its canonical form 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, MinMaxLP] = ... 10 | % standard2canonical(A, c, b, Eqin, MinMaxLP) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- MinMaxLP: the type of optimization 22 | % 23 | % Output: 24 | % -- A: transformed matrix of coefficients of the 25 | % constraints (size m x n) 26 | % -- c: transformed vector of coefficients of the objective 27 | % function (size n x 1) 28 | % -- b: transformed vector of the right-hand side of the 29 | % constraints (size m x 1) 30 | % -- Eqin: transformed vector of the type of the 31 | % constraints (size m x 1) 32 | % -- MinMaxLP: the type of optimization 33 | 34 | [m, ~] = size(A); % size of matrix A 35 | % find all constraints that are not in the form 'less than 36 | % or equal to' 37 | for i = 1:m 38 | if Eqin(i) == 0 % transform equality constraints 39 | f = find(A(i, :) > 0); 40 | f = f(1); 41 | b(i) = b(i) / A(i, f); 42 | A(i, :) = A(i, :) / A(i, f); 43 | Eqin(i) = -1; 44 | A(:, f) = []; 45 | c(f) = []; 46 | end 47 | end 48 | end -------------------------------------------------------------------------------- /codes/chapter3/GenerateRandomLPs.m: -------------------------------------------------------------------------------- 1 | function GenerateRandomLPs 2 | % Filename: GenerateRandomLPs.m 3 | % Description: Custom menu for creating random LPs 4 | % Authors: Ploskas, N., & Samaras, N. 5 | % 6 | % Syntax: GenerateRandomLPs 7 | % 8 | % Input: None 9 | % 10 | % Output: files that store the generated random LPs 11 | 12 | choice = 0; 13 | while choice ~= 4 14 | % show menu 15 | choice = menu('Generate Random LPs', ... 16 | 'Generator Initialization', 'Dense Random LPs', ... 17 | 'Sparse Random LPs', 'Exit'); 18 | if choice == 1 % initialize generator 19 | seedNumber = input('Please give the seed number: '); 20 | rand('state', seedNumber); 21 | sprand('state'); 22 | elseif choice == 2 % create dense random LPs 23 | m = input('Please give the number of constraints: '); 24 | n = input('Please give the number of variables: '); 25 | denseMenu(m, n); 26 | elseif choice == 3 % create sparse random LPs 27 | m = input('Please give the number of constraints: '); 28 | n = input('Please give the number of variables: '); 29 | sparseMenu(m, n); 30 | elseif choice == 4 % exit 31 | return; 32 | end 33 | end 34 | end -------------------------------------------------------------------------------- /codes/chapter3/denseMenu.m: -------------------------------------------------------------------------------- 1 | function denseMenu(m, n) 2 | % Filename: denseMenu.m 3 | % Description: Custom menu for creating dense random LPs 4 | % Authors: Ploskas, N., & Samaras, N. 5 | % 6 | % Syntax: denseMenu(m, n) 7 | % 8 | % Input: 9 | % -- m: the number of constraints of the generated random LPs 10 | % -- n: the number of variables of the generated random LPs 11 | % 12 | % Output: files that store the generated dense random LPs 13 | 14 | % read the directory to store the LPs 15 | pathName = input(['Please give the path where you want ' ... 16 | 'to store the generated LPs: ']); 17 | % read the number of the LPs to generate 18 | nOfProblems = input(['Please give the number of the LPs ' ... 19 | 'that you want to create: ']); 20 | % read the ranges of the values for matrix A 21 | Alu = input(['Please give the range of the values for ' ... 22 | 'matrix A: ']); 23 | % read the ranges of the values for vector c 24 | clu = input(['Please give the range of the values for ' ... 25 | 'vector c: ']); 26 | % read the type of optimization 27 | optType = input(['Please give the type of optimization ' ... 28 | '(0 min, 1 max, 2 random): ']); 29 | % read if all LPs will be optimal 30 | optimality = input(['Do you want all the LPs to be ' ... 31 | 'optimal (1 yes, 2 no): ']); 32 | if optimality == 1 % optimal LPs 33 | % read the center of the circle 34 | center = input(['Please give the center of the circle: ']); 35 | % read the radius of the circle 36 | R = input(['Please give the radius of the circle ' ... 37 | '(must be less than the center of the circle: ']); 38 | while R >= center % read R 39 | R = input(['Please give the radius of the circle ' ... 40 | '(must be less than the center of the circle: ']); 41 | end 42 | % create nOfProblems dense random optimal LPs 43 | for i = 1:nOfProblems 44 | [A, c, b, Eqin, MinMaxLP] = denseRandomOptimal(m, n, ... 45 | optType, Alu, clu, center, R); 46 | s1 = num2str(m); 47 | s2 = num2str(n); 48 | k = num2str(i); 49 | fname = [pathName '/' 'fdata' k '_' s1 'x' s2]; 50 | Name = ['fdata' k '_' s1 'x' s2]; 51 | R = []; 52 | BS = []; 53 | NonZeros = nnz(A); 54 | c0 = 0; 55 | c00 = 0; 56 | % save variables in a MAT file 57 | eval(['save ' fname '.mat A c b Eqin MinMaxLP Name ' ... 58 | 'R BS NonZeros c0 c00']); 59 | end 60 | else % not optimal LPs 61 | % read the ranges of the values for vector b 62 | blu = input(['Please give the range of the values for ' ... 63 | 'vector b: ']); 64 | % read the ranges of the values for vector Eqin 65 | Eqinlu = input(['Please give the range of the values ' ... 66 | 'for vector Eqin (0 - equality constraints, 1 - ' ... 67 | ' less than or equal to inequality constraints, ' ... 68 | ' 2 - greater than or equal to inequality ' ... 69 | 'constraints: ']); 70 | for i = 1:nOfProblems % create nOfProblems dense random LPs 71 | [A, c, b, Eqin, MinMaxLP] = denseRandom(m, n, ... 72 | optType, Alu, clu, blu, Eqinlu); 73 | s1 = num2str(m); 74 | s2 = num2str(n); 75 | k = num2str(i); 76 | fname = [pathName '/' 'fdata' k '_' s1 'x' s2]; 77 | Name = ['fdata' k '_' s1 'x' s2]; 78 | R = []; 79 | BS = []; 80 | NonZeros = nnz(A); 81 | c0 = 0; 82 | c00 = 0; 83 | % save variables in a MAT file 84 | eval(['save ' fname '.mat A c b Eqin MinMaxLP Name ' ... 85 | 'R BS NonZeros c0 c00']); 86 | end 87 | end 88 | end -------------------------------------------------------------------------------- /codes/chapter3/denseRandom.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP]= denseRandom(m, n, ... 2 | optType, Alu, clu, blu, Eqinlu) 3 | % Filename: denseRandom.m 4 | % Description: Creates dense random LPs 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, MinMaxLP, Eqin]= denseRandom(m, n, ... 8 | % minCard, Alu, clu, blu, Eqinlu) 9 | % 10 | % Input: 11 | % -- m: the number of constraints of the generated random 12 | % LPs 13 | % -- n: the number of variables of the generated random 14 | % LPs 15 | % -- optType: the type of optimization (0 min, 1 max, 2 16 | % random) 17 | % -- Alu: the ranges of the values for matrix A 18 | % (size 1 x 2) 19 | % -- clu: the ranges of the values for vector c 20 | % (size 1 x 2) 21 | % -- blu: the ranges of the values for vector b 22 | % (size 1 x 2) 23 | % -- Eqinlu: the ranges of the values for vector Eqin 24 | % (size 1 x 2) 25 | % 26 | % Output: 27 | % -- A: matrix of coefficients of the constraints 28 | % (size m x n) 29 | % -- c: vector of coefficients of the objective function 30 | % (size n x 1) 31 | % -- b: vector of the right-hand side of the constraints 32 | % (size m x 1) 33 | % -- Eqin: vector of the type of the constraints 34 | % (size m x 1) 35 | % -- MinMaxLP: the type of optimization 36 | 37 | Al = Alu(1); % get the lower bound of A 38 | Au = Alu(2); % get the upper bound of A 39 | % create matrix A 40 | A = floor((Au - Al + 1) * rand(m, n)) + Al; 41 | cl = clu(1); % get the lower bound of c 42 | cu = clu(2); % get the upper bound of c 43 | % create vector c 44 | c = floor((cu - cl + 1) * rand(n, 1)) + cl; 45 | bl = blu(1); % get the upper bound of b 46 | bu = blu(2); % get the upper bound of c 47 | % create vector b 48 | b = floor((bu - bl + 1) * rand(m, 1)) + bl; 49 | eqinl = Eqinlu(1); % get the lower bound of Eqin 50 | eqinu = Eqinlu(2); % get the upper bound of Eqin 51 | % create vector Eqin 52 | Eqin = floor((eqinu - eqinl + 1) * rand(m, 1)) + eqinl; 53 | % less than or equal to inequality constraints 54 | Eqin(Eqin == 1) = -1; 55 | % greater than or equal to inequality constraints 56 | Eqin(Eqin == 2) = 1; 57 | if optType == 0 % minimization 58 | MinMaxLP = -1; 59 | elseif optType == 1 % maximization 60 | MinMaxLP = 1; 61 | else % pick random optimization type 62 | MinMaxLP = -1; 63 | if randi(2) < 2 64 | MinMaxLP = 1; 65 | end 66 | end 67 | end -------------------------------------------------------------------------------- /codes/chapter3/denseRandomOptimal.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = ... 2 | denseRandomOptimal(m, n, optType, Alu, clu, center, R) 3 | % Filename: denseRandomOptimal.m 4 | % Description: Creates dense random optimal LPs 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, Eqin, MinMaxLP] = ... 8 | % denseRandomOptimal(m, n, optType, Alu, clu, center, R) 9 | % 10 | % Input: 11 | % -- m: the number of constraints of the generated random 12 | % LPs 13 | % -- n: the number of variables of the generated random 14 | % LPs 15 | % -- optType: the type of optimization (0 min, 1 max, 2 16 | % random) 17 | % -- Alu: the ranges of the values for matrix A 18 | % (size 1 x 2) 19 | % -- clu: the ranges of the values for vector c 20 | % (size 1 x 2) 21 | % -- center: the center of the circle 22 | % -- R: the radius of the circle 23 | 24 | % Output: 25 | % -- A: matrix of coefficients of the constraints 26 | % (size m x n) 27 | % -- c: vector of coefficients of the objective function 28 | % (size n x 1) 29 | % -- b: vector of the right-hand side of the constraints 30 | % (size m x 1) 31 | % -- Eqin: vector of the type of the constraints 32 | % (size m x 1) 33 | % -- MinMaxLP: the type of optimization 34 | % 35 | cl = clu(1); % get the lower bound of c 36 | cu = clu(2); % get the upper bound of c 37 | % create vector c 38 | c = round((cu - cl + 1) * randn(n, 1)) + cl; 39 | Al = Alu(1); % get the lower bound of A 40 | Au = Alu(2); % get the upper bound of A 41 | A = zeros(m, n); 42 | b = zeros(m, 1); 43 | k = ones(1, n) * center; 44 | for i = 1:m % create matrix A and vector b 45 | % create a row of matrix A 46 | a = round((Au - Al + 1) * rand(1, n)) + Al; 47 | % calculate the hyperplane that is tangent 48 | % in a random point of the sphere 49 | y = k + r * (a / norm(a)); 50 | b0 = a * y'; 51 | b(i, 1) = b0; % add the point to vector b 52 | A(i, :) = a; % add the row to matrix A 53 | end 54 | % create vector Eqin 55 | Eqin(1:m, 1) = -1; 56 | if optType == 0 % minimization 57 | MinMaxLP = -1; 58 | elseif optType == 1 % maximization 59 | MinMaxLP = 1; 60 | else % pick random optimization type 61 | MinMaxLP = -1; 62 | if randi(2) < 2 63 | MinMaxLP = 1; 64 | end 65 | end 66 | end -------------------------------------------------------------------------------- /codes/chapter3/example1_1.mps: -------------------------------------------------------------------------------- 1 | NAME EXAMPLE1_1 2 | ROWS 3 | N OBJ 4 | G R1 5 | E R2 6 | L R3 7 | E R4 8 | G R5 9 | G R6 10 | L R7 11 | COLUMNS 12 | X1 R2 4 13 | X1 R3 -3 14 | X1 R4 4 15 | X1 R5 1 16 | X1 OBJ -2 17 | X2 R1 2 18 | X2 R2 -3 19 | X2 R3 2 20 | X2 OBJ 4 21 | X3 R1 3 22 | X3 R2 8 23 | X3 R4 -1 24 | X3 R6 1 25 | X3 R7 1 26 | X3 OBJ -2 27 | X4 R2 -1 28 | X4 R3 -4 29 | X4 R4 4 30 | X4 OBJ 2 31 | RHS 32 | RHS1 R1 6 33 | RHS1 R2 20 34 | RHS1 R3 -8 35 | RHS1 R4 18 36 | RHS1 R5 1 37 | RHS1 R6 2 38 | RHS1 R7 10 39 | BOUNDS 40 | FR BND1 X1 41 | FR BND1 X3 42 | ENDATA -------------------------------------------------------------------------------- /codes/chapter3/example1_2.mps: -------------------------------------------------------------------------------- 1 | NAME EXAMPLE1_2 2 | ROWS 3 | N OBJ 4 | G R1 5 | E R2 6 | L R3 7 | E R4 8 | COLUMNS 9 | X1 R2 4 10 | X1 R3 -3 11 | X1 R4 4 12 | X1 OBJ -2 13 | X2 R1 2 14 | X2 R2 -3 15 | X2 R3 2 16 | X2 OBJ 4 17 | X3 R1 3 18 | X3 R2 8 19 | X3 R4 -1 20 | X3 OBJ -2 21 | X4 R2 -1 22 | X4 R3 -4 23 | X4 R4 4 24 | X4 OBJ 2 25 | RHS 26 | RHS1 R1 6 27 | RHS1 R2 20 28 | RHS1 R3 -8 29 | RHS1 R4 18 30 | BOUNDS 31 | LO BND1 X1 1 32 | LO BND1 X3 2 33 | UP BND1 X3 10 34 | ENDATA -------------------------------------------------------------------------------- /codes/chapter3/example1_3.mps: -------------------------------------------------------------------------------- 1 | NAME EXAMPLE1_3 2 | ROWS 3 | N OBJ 4 | G R1 5 | E R2 6 | L R3 7 | E R4 8 | COLUMNS 9 | X1 R2 4 R3 -3 10 | X1 R4 4 OBJ -2 11 | X2 R1 2 R2 -3 12 | X2 R3 2 OBJ 4 13 | X3 R1 3 R2 8 14 | X3 R4 -1 OBJ -2 15 | X4 R2 -1 R3 -4 16 | X4 R4 4 OBJ 2 17 | RHS 18 | B1 R1 6 R2 20 19 | B1 R3 -8 R4 18 20 | BOUNDS 21 | LO BND1 X1 1 22 | LO BND1 X3 2 23 | UP BND1 X3 10 24 | ENDATA -------------------------------------------------------------------------------- /codes/chapter3/example2.mps: -------------------------------------------------------------------------------- 1 | NAME EXAMPLE2 2 | ROWS 3 | N OBJ 4 | L R1 5 | G R2 6 | E R3 7 | COLUMNS 8 | X1 R1 1 R2 1 9 | X1 OBJ 1 10 | X2 R1 1 R3 -1 11 | X2 OBJ 4 12 | X3 R2 1 R3 1 13 | X3 OBJ 9 14 | RHS 15 | B1 R1 5 R2 10 16 | B1 R3 7 17 | BOUNDS 18 | UP BND1 X1 4 19 | LO BND1 X2 -1 20 | UP BND1 X2 1 21 | ENDATA -------------------------------------------------------------------------------- /codes/chapter3/mat2mps.m: -------------------------------------------------------------------------------- 1 | function mat2mps(filename) 2 | % Filename: mat2mps.m 3 | % Description: Converts a MAT file to an MPS file 4 | % Authors: Ploskas, N., & Samaras, N., Triantafyllidis, Ch. 5 | % 6 | % Syntax: mat2mps(filename) 7 | % 8 | % Input: 9 | % -- filename: the name of the MAT file (without the .mat 10 | % extension) 11 | % 12 | % Output: an MPS file named filename.mps 13 | 14 | % copy the specified file to matlab.mat 15 | copyfile([filename '.mat'], 'matlab.mat'); 16 | load; % load file 17 | A = full(A); % make A full 18 | b = full(b); % make b full 19 | c = full(c); % make c full 20 | Eqin = full(Eqin); % make Eqin full 21 | C = c; % copy c to C 22 | B = b; % copy b to B 23 | % if MinMaxLP does not exist, the LP problem is minimization 24 | if exist('MinMaxLP', 'var') == 0 25 | MinMaxLP = -1; 26 | end 27 | % if the Name does not exist, use the filename 28 | if exist('Name', 'var') == 0 29 | Name = filename; 30 | end 31 | % if R does not exist, set to empty 32 | if exist('R', 'var') == 0 33 | R = []; 34 | else 35 | R = full(R); 36 | end 37 | % if BS does not exist, set to empty 38 | if exist('BS','var') == 0 39 | BS = []; 40 | else 41 | BS = full(BS); 42 | end 43 | % create an mps file with the same name of the LP and write 44 | % MPS filename to it 45 | y = length(Name); 46 | Name2 = Name; 47 | Name(1, y + 1) = '.'; 48 | Name(1, y + 2) = 'm'; 49 | Name(1, y + 3) = 'p'; 50 | Name(1, y + 4) = 's'; 51 | fid = fopen(Name, 'wt'); 52 | id = ['NAME ',Name2]; 53 | fprintf(fid, '%s', id); 54 | for i = 1:50 + (8 - y) 55 | nullname(i) = ' '; 56 | end 57 | % write the type of optimization to the MPS file 58 | if MinMaxLP == -1 % minimization 59 | fprintf(fid, '%s', nullname); 60 | fprintf(fid, '%s', '( MIN)'); 61 | elseif MinMaxLP == 1 % maximization 62 | fprintf(fid, '%s', nullname); 63 | fprintf(fid, '%s', '( MAX)'); 64 | end 65 | % create ROWS section 66 | fprintf(fid, '\n'); 67 | fprintf(fid, '%s', 'ROWS'); % print the ROWS header 68 | fprintf(fid, '\n'); 69 | obj = [' N OBJ']; 70 | fprintf(fid, '%s', obj); % print the objective function 71 | fprintf(fid, '\n'); 72 | a = length(Eqin); 73 | Eqin2 = {}; 74 | for i = 1:a 75 | if Eqin(i) == -1 % less than or equal to constraint 76 | Eqin2{i} = 'L'; 77 | elseif Eqin(i) == 0 % equality constraint 78 | Eqin2{i} = 'E'; 79 | elseif Eqin(i) == 1 % greater than or equal to constraint 80 | Eqin2{i} = 'G'; 81 | end 82 | end 83 | Eqin2 = cell2mat(Eqin2); % convert cell to matrix 84 | for i = 1:a % print constraints 85 | fprintf(fid, '%s', ' '); 86 | fprintf(fid, '%s', Eqin2(i)); 87 | fprintf(fid, '%s', ' '); 88 | fprintf(fid, '%s', 'R'); 89 | fprintf(fid, '%i', i); 90 | fprintf(fid, '\n'); 91 | end 92 | % create COLUMNS section 93 | fprintf(fid, '%s', 'COLUMNS'); % print COLUMNS header 94 | [a, b] = size(A); 95 | fprintf(fid, '\n'); 96 | for i = 1:b % column-oriented 97 | if i > 1 98 | if C(i - 1) ~= 0 % new line after each record 99 | fprintf(fid, '\n'); 100 | end 101 | end 102 | j = 1; 103 | while j <= a 104 | if A(j, i) ~= 0 % print the constraint matrix A 105 | fprintf(fid, '%s', ' X'); 106 | fprintf(fid, '%i', i); 107 | szcount = num2str(i); 108 | y = length(szcount); 109 | k = 5 - y; 110 | for m = 1:k 111 | fprintf(fid, '%s', ' '); 112 | end 113 | fprintf(fid, '%s', ' '); 114 | fprintf(fid, '%s', 'R'); 115 | fprintf(fid, '%i', j); 116 | szcount = num2str(j); 117 | y = length(szcount); 118 | k = 5 - y; 119 | for m = 1:k 120 | fprintf(fid, '%s', ' '); 121 | end 122 | fprintf(fid, '%s', ' '); 123 | fprintf(fid, '%f', A(j, i)); 124 | fprintf(fid, '\n'); 125 | end 126 | if j < a 127 | j = j + 1; 128 | else 129 | if C(i) ~= 0 % print the objective function 130 | fprintf(fid, '%s', ' X'); 131 | fprintf(fid, '%i', i); 132 | szcount = num2str(i); 133 | y = length(szcount); 134 | k = 5 - y; 135 | for m = 1:k 136 | fprintf(fid, '%s', ' '); 137 | end 138 | fprintf(fid, '%s', ' '); 139 | fprintf(fid, '%s', 'OBJ'); 140 | fprintf(fid, '%s', ' '); 141 | fprintf(fid, '%f', C(i)); 142 | if i == b 143 | if j == a 144 | fprintf(fid, '\n'); 145 | end 146 | end 147 | end 148 | break 149 | end 150 | end 151 | end 152 | % create RHS section 153 | fprintf(fid, '%s', 'RHS'); % print the RHS header 154 | fprintf(fid, '\n'); 155 | a = length(B); 156 | for i = 1:a % print each right-hand side 157 | fprintf(fid, '%s', ' RHS1'); 158 | fprintf(fid, '%s', ' '); 159 | fprintf(fid, '%s', 'R'); 160 | fprintf(fid, '%i', i); 161 | szcount = num2str(i); 162 | y = length(szcount); 163 | k = 5 - y; 164 | for m = 1:k 165 | fprintf(fid, '%s', ' '); 166 | end 167 | fprintf(fid, '%s', ' '); 168 | fprintf(fid, '%f', B(i)); 169 | fprintf(fid, '\n'); 170 | end 171 | % write the objective constants if exist 172 | objconst = []; 173 | if exist('c00', 'var') == 1 174 | if exist('c0', 'var') == 1 175 | objconst = c00 - c0; 176 | else 177 | objconst = c00; 178 | end 179 | else 180 | if exist('c0', 'var') == 1 181 | objconst = -c0; 182 | else 183 | objconst = []; 184 | end 185 | end 186 | if ~isempty(objconst) 187 | if objconst ~= 0 188 | fprintf(fid, '%s', ' RHS1'); 189 | fprintf(fid, '%s', ' '); 190 | fprintf(fid, '%s', 'OBJ'); 191 | fprintf(fid, '%s', ' '); 192 | fprintf(fid, '%f', objconst); 193 | fprintf(fid, '\n'); 194 | end 195 | end 196 | % create RANGES section 197 | if isempty(R) ~= 1 198 | fprintf(fid, '%s', 'RANGES'); % print the RANGES header 199 | fprintf(fid, '\n'); 200 | [a, ~] = size(R); 201 | for i = 1:a % print all ranges 202 | fprintf(fid, '%s', ' RANGE1'); 203 | fprintf(fid, '%s', ' '); 204 | fprintf(fid, '%s', 'R'); 205 | fprintf(fid, '%i', R(i, 1)); 206 | szcount = num2str(R(i, 1)); 207 | y = length(szcount); 208 | k = 5 - y; 209 | for m = 1:k 210 | fprintf(fid, '%s', ' '); 211 | end 212 | fprintf(fid, '%s', ' '); 213 | if Eqin(R(i, 1)) == -1 214 | if R(i, 4) == 1 215 | fprintf(fid, '%f', -(R(i, 2) - B(R(i, 1)))); 216 | fprintf(fid, '\n'); 217 | else 218 | fprintf(fid, '%f', R(i, 2) - B(R(i, 1))); 219 | fprintf(fid, '\n'); 220 | end 221 | elseif Eqin(R(i, 1)) == 0 222 | if R(i, 4) == 1 223 | fprintf(fid, '%f', R(i, 3) - B(R(i, 1))); 224 | fprintf(fid, '\n'); 225 | else 226 | fprintf(fid, '%f', R(i, 2) - B(R(i, 1))); 227 | fprintf(fid, '\n'); 228 | end 229 | elseif Eqin(R(i, 1)) == 1 230 | if R(i, 4) == 1 231 | fprintf(fid, '%f', R(i, 3) - R(i, 2)); 232 | fprintf(fid, '\n'); 233 | else 234 | fprintf(fid, '%f', -(R(i, 3) - R(i, 2))); 235 | fprintf(fid, '\n'); 236 | end 237 | end 238 | end 239 | end 240 | % create BOUNDS section 241 | if isempty(BS) ~= 1 242 | fprintf(fid, '%s', 'BOUNDS'); % print the BOUNDS header 243 | fprintf(fid, '\n'); 244 | a = length(BS); 245 | for i = 1:a % print each bound 246 | if BS(i, 2) == -1 247 | fprintf(fid, '%s', ' UP'); 248 | elseif BS(i, 2) == 1 249 | fprintf(fid, '%s', ' LO'); 250 | elseif BS(i, 2) == 0 251 | fprintf(fid, '%s', ' FX'); 252 | elseif BS(i, 2) == 11 253 | fprintf(fid, '%s', ' FR'); 254 | elseif BS(i, 2) == 111 255 | fprintf(fid, '%s', ' MI'); 256 | elseif BS(i, 2) == 1111 257 | fprintf(fid, '%s', ' PL'); 258 | end 259 | fprintf(fid, '%s', ' '); 260 | fprintf(fid, '%s', 'BOUND1 '); 261 | fprintf(fid, '%s', 'X'); 262 | fprintf(fid, '%i', BS(i, 1)); 263 | % write the value field for LO, UP, and FX type of 264 | % constraints 265 | if BS(i, 2) == -1 || BS(i, 2) == 1 || BS(i, 2) == 0 266 | szcount = num2str(i); 267 | y = length(szcount); 268 | k = 7 - y; 269 | for m = 1:k 270 | fprintf(fid, '%s', ' '); 271 | end 272 | fprintf(fid, '%s', ' '); 273 | fprintf(fid, '%f', BS(i,3)); 274 | fprintf(fid, '\n'); 275 | else 276 | fprintf(fid, '\n'); 277 | end 278 | end 279 | end 280 | % write the ENDATA header 281 | fprintf(fid, '%s', 'ENDATA'); 282 | fclose(fid); % close the file 283 | delete matlab.mat % delete matlab.mat 284 | end -------------------------------------------------------------------------------- /codes/chapter3/mps2mat.m: -------------------------------------------------------------------------------- 1 | function mps2mat(filename) 2 | % Filename: mps2mat.m 3 | % Description: Converts an MPS file to a MAT file 4 | % Authors: Ploskas, N., & Samaras, N., Triantafyllidis, Ch. 5 | % 6 | % Syntax: mps2mat(filename) 7 | % 8 | % Input: 9 | % -- filename: the name of the MPS file (without the .mps 10 | % extension) 11 | % 12 | % Output: a MAT file named filename.mat 13 | 14 | % set the search starting point to 1 15 | searchStartingPoint = 1; 16 | % create an empty vector for the objective constant 17 | c0 = []; 18 | % add the extension to the mps file 19 | mpsFilename = [filename '.mps']; 20 | % find a rough estimation for the number of variables and 21 | % the nonzero elements 22 | s = dir(mpsFilename); 23 | filesize = s.bytes; 24 | estimation = floor(filesize / 220); 25 | nnzmax = floor((filesize / 30)); 26 | fid = fopen(mpsFilename, 'rt'); % open the file 27 | Eqin = []; % create an empty vector for Eqin 28 | MinMaxLP = []; % create an empty vector for MinMaxLP 29 | % find the name of the problem and the optimization 30 | % direction 31 | line = fgets(fid); 32 | % read the NAME header 33 | useless = sscanf(line(1, 1:4), '%s%', 1); 34 | % if the optimization direction is included 35 | if length(line) > 23 36 | % read the Name 37 | Name = sscanf(line(1, 15:23), '%s%', 1); 38 | % read the optimization direction 39 | MinMaxLP = sscanf(line(1, 75:length(line)), '%s%', 1); 40 | else % if the optimization direction is not included 41 | % read the name 42 | Name = sscanf(line(1, 15:length(line)), '%s%', 1); 43 | MinMaxLP = []; % optimization direction does not exist 44 | end 45 | % if the optimization direction is not empty 46 | if isempty(MinMaxLP) ~= 1 47 | if isequal(MinMaxLP, 'MIN') == 1 % minimization 48 | MinMaxLP = -1; 49 | elseif isequal(MinMaxLP, 'MAX') == 1 % maximization 50 | MinMaxLP = 1; 51 | end 52 | else % if it is empty, the default is minimization 53 | MinMaxLP = -1; 54 | end 55 | fgetl(fid); 56 | constraintType = ''; 57 | objPos = 1; 58 | k = 1; 59 | lineE = 1; 60 | % read the ROWS section and populate vector Eqin 61 | while isequal(constraintType, 'COLUMNS') == 0 62 | % get the name and type of the constraints 63 | constraintType = fscanf(fid, '%s%', 1); 64 | if isequal(constraintType, 'COLUMNS') ~= 1 65 | constraintName = fscanf(fid, '%s%', 1); 66 | else % break when you read the COLUMNS header 67 | break 68 | end 69 | X{k, 1} = constraintType; 70 | X{k, 2} = constraintName; 71 | if isequal(X{k, 1}, 'N') == 1 % objective function 72 | objPos = k; 73 | ant = X{k, 2}; 74 | % equality constraint 75 | elseif isequal(constraintType, 'E' ) == 1 76 | Eqin(lineE) = 0; 77 | lineE = lineE + 1; 78 | % less than or equal to constraint 79 | elseif isequal(constraintType, 'L') == 1 80 | Eqin(lineE) = -1; 81 | lineE = lineE + 1; 82 | % greater than or equal to constraint 83 | elseif isequal(constraintType, 'G') == 1 84 | Eqin(lineE) = 1; 85 | lineE = lineE + 1; 86 | end 87 | k = k + 1; 88 | end 89 | Eqin = Eqin'; % transpose Eqin 90 | % read COLUMNS section and populate vector c and matrix A 91 | X(objPos, :) = []; 92 | [m, ~] = size(X); 93 | A = spalloc(m, estimation, nnzmax); % preallocate matrix A 94 | B = zeros(m, 1); %create vector B 95 | C = {}; % create cell C 96 | R = []; % create vector R 97 | BS = {}; % create vector BS 98 | clmn = 1; 99 | variables = {}; 100 | objectivity = 0; 101 | fgets(fid); 102 | D = X(:, 2); 103 | flag = 0; 104 | [a, ~] = size(D); 105 | D{a + 1, :} = ant; 106 | D = char(D); 107 | mas = length(D); 108 | objInd = a + 1; 109 | % read the first line in COLUMNS header 110 | line = fgets(fid); 111 | b = length(line); 112 | % read the variable name, the constraint name and the value 113 | varname = sscanf(line(1, 5:12), '%s%', 1); 114 | varpos = sscanf(line(1, 15:22), '%s%', 1); 115 | value = sscanf(line(1, 25:b), '%s%', 1); 116 | value = str2double(value); 117 | if b > 40 % read the fifth and the sixth fields if exist 118 | flag = 1; 119 | varpos2 = sscanf(line(1, 40:b), '%s%', 1); 120 | value2 = str2double(line(1, 50:b)); 121 | end 122 | % check if during the reading we changed the current variable 123 | if objectivity == 0 124 | C{clmn} = 0; 125 | else 126 | objectivity = 0; 127 | end 128 | currentvar = varname; 129 | clmn = clmn + 1; 130 | variables{clmn, 1} = currentvar; 131 | k = strmatch(varpos, D, 'exact'); 132 | % store the value to vector C if the variable refers to the 133 | % objective function 134 | if k == objInd 135 | C{clmn} = value; 136 | objectivity = 1; 137 | else 138 | A(k, clmn) = value; % store to matrix A 139 | end 140 | if b > 40 % if exists the fifth and sixth fields 141 | k2 = strmatch(varpos2, D, 'exact'); 142 | % store the value to vector C if the variable refers to 143 | % the objective function 144 | if k2 == objInd 145 | C{clmn} = value2; 146 | objectivity = 1; 147 | else 148 | A(k2, clmn) = value2; % store to matrix A 149 | end 150 | end 151 | % read the second line in COLUMNS header 152 | varname = ''; 153 | varpos = ''; 154 | value = ''; 155 | varpos2 = ''; 156 | value2 = ''; 157 | line = fgets(fid); 158 | b = length(line); 159 | % if we reached the RHS section 160 | if isequal(line(1, 1:3), 'RHS') 161 | if objectivity == 0 162 | C{clmn} = 0; 163 | end 164 | end 165 | % read the variable name, the constraint name and the value 166 | varname = sscanf(line(1, 5:12), '%s%', 1); 167 | varpos = sscanf(line(1, 15:22), '%s%', 1); 168 | value = sscanf(line(1, 25:b), '%s%', 1); 169 | value = str2double(value); 170 | if b > 40 % read the fifth and the sixth fields if exist 171 | varpos2 = sscanf(line(1, 40:48), '%s%', 1); 172 | value2 = str2double(line(1, 50:b)); 173 | flag = 1; 174 | end 175 | % if the variable changes, then we must reset the starting 176 | % point of the search 177 | if isequal(varname, currentvar) == 0 178 | searchStartingPoint = 1; 179 | % check if during the reading we changed the current 180 | % variable 181 | if objectivity == 0 182 | C{clmn} = 0; 183 | else 184 | objectivity = 0; 185 | end 186 | currentvar = varname; 187 | clmn = clmn + 1; 188 | variables{clmn, 1} = currentvar; 189 | end 190 | k = strmatch(varpos, D(searchStartingPoint:mas, :), ... 191 | 'exact'); 192 | if searchStartingPoint ~= 1 193 | k = k + searchStartingPoint - 1; 194 | end 195 | if isempty(k) 196 | k = strmatch(varpos, D(1:searchStartingPoint - 1, ... 197 | :),'exact'); 198 | end 199 | searchStartingPoint = k + 1; 200 | % store the value to vector C if the variable refers to 201 | % the objective function 202 | if k == objInd 203 | C{clmn} = value; 204 | objectivity = 1; 205 | else 206 | % store to matrix A 207 | A(k, clmn) = value; 208 | end 209 | if b > 40 % if exists the fifth and sixth fields 210 | k2 = strmatch(varpos2, D(searchStartingPoint:mas, ... 211 | :), 'exact'); 212 | if searchStartingPoint ~= 1 213 | k2 = k2 + searchStartingPoint - 1; 214 | end 215 | if isempty(k2) 216 | k2 = strmatch(varpos2, D(1:searchStartingPoint ... 217 | - 1, :), ... 218 | 'exact'); 219 | end 220 | searchStartingPoint = k2 + 1; 221 | % store the value to vector C if the variable refers to 222 | % the objective function 223 | if k2 == objInd 224 | C{clmn} = value2; 225 | objectivity = 1; 226 | else 227 | A(k2, clmn) = value2; % store to matrix A 228 | end 229 | end 230 | % read the rest of the records of COLUMNS section 231 | % set the first found index to use later for faster search 232 | searchStartingPoint = k + 1; 233 | flag = 1; 234 | if flag == 1 235 | % stop when you reach the RHS section 236 | while isequal(varname, 'RHS') == 0 237 | varname = ''; 238 | varpos = ''; 239 | value = ''; 240 | varpos2 = ''; 241 | value2 = ''; 242 | line = fgets(fid); 243 | b = length(line); 244 | % if we reach the RHS section, then break the loop 245 | if isequal(line(1, 1:3),'RHS') 246 | if objectivity == 0 247 | C{clmn} = 0; 248 | end 249 | break 250 | end 251 | % read the variable name, the constraint name and 252 | % the value 253 | varname = sscanf(line(1, 5:12), '%s%', 1); 254 | varpos = sscanf(line(1, 15:22), '%s%', 1); 255 | value = sscanf(line(1, 25:b), '%s%', 1); 256 | value = str2double(value); 257 | % read the fifth and the sixth fields if exist 258 | if b > 40 259 | varpos2 = sscanf(line(1, 40:b), '%s%', 1); 260 | value2 = str2double(line(1, 50:b)); 261 | end 262 | if isequal(varname, currentvar) == 0 263 | % if the variable changes, then we must reset 264 | % the starting point of the search 265 | searchStartingPoint = 1; 266 | % check if during the reading we changed the 267 | % current variable 268 | if objectivity == 0 269 | C{clmn} = 0; 270 | else 271 | objectivity = 0; 272 | end 273 | currentvar = varname; 274 | clmn = clmn + 1; 275 | variables{clmn, 1} = currentvar; 276 | end 277 | k = strmatch(varpos, D(searchStartingPoint:mas, ... 278 | :), 'exact'); 279 | if searchStartingPoint ~= 1 280 | k = k + searchStartingPoint - 1; 281 | end 282 | if isempty(k) 283 | k = strmatch(varpos, D(1:searchStartingPoint ... 284 | - 1, :), 'exact'); 285 | end 286 | searchStartingPoint = k + 1; 287 | % store the value to vector C if the variable refers 288 | % to the objective function 289 | if k == objInd 290 | C{clmn} = value; 291 | objectivity = 1; 292 | else 293 | % store to matrix A 294 | A(k, clmn) = value; 295 | end 296 | if b > 40 % if exists the fifth and sixth fields 297 | k2 = strmatch(varpos2, ... 298 | D(searchStartingPoint:mas, :), 'exact'); 299 | if searchStartingPoint ~= 1 300 | k2 = k2 + searchStartingPoint - 1; 301 | end 302 | if isempty(k2) 303 | k2 = strmatch(varpos2, ... 304 | D(1:searchStartingPoint - 1, :), ... 305 | 'exact'); 306 | end 307 | searchStartingPoint = k2 + 1; 308 | % store the value to vector C if the variable 309 | % refers to the objective function 310 | if k2 == objInd 311 | C{clmn} = value2; 312 | objectivity = 1; 313 | else 314 | A(k2, clmn) = value2; % store to matrix A 315 | end 316 | end 317 | end 318 | end 319 | % process the final record of COLUMNS section 320 | if flag == 0 321 | % stop when the RHS section is reached 322 | while isequal(varname, 'RHS') == 0 323 | varname = ''; 324 | varpos = ''; 325 | value = ''; 326 | line = fgets(fid); 327 | b = length(line); 328 | if isequal(line(1, 1:3), 'RHS') 329 | if objectivity == 0 330 | C{clmn} = 0; 331 | end 332 | break 333 | end 334 | % read the variable name, the constraint name and 335 | % the value 336 | varname = sscanf(line(1, 5:12), '%s%', 1); 337 | varpos = sscanf(line(1, 15:22), '%s%', 1); 338 | value = sscanf(line(1, 25:b), '%s%', 1); 339 | value = str2double(value); 340 | if isequal(varname, currentvar) == 0 341 | % if the variable changes, then we must reset 342 | % the starting point of the search 343 | searchStartingPoint = 1; 344 | % check if during the reading we changed the 345 | % current variable 346 | if objectivity == 0 347 | C{clmn} = 0; 348 | else 349 | objectivity = 0; 350 | end 351 | currentvar = varname; 352 | clmn = clmn + 1; 353 | variables{clmn, 1} = currentvar; 354 | end 355 | k = strmatch(varpos, ... 356 | D(searchStartingPoint:mas, :), 'exact'); 357 | if searchStartingPoint ~= 1 358 | k = k + searchStartingPoint - 1; 359 | end 360 | if isempty(k) 361 | k = strmatch(varpos, ... 362 | D(1:searchStartingPoint - 1, :), 'exact'); 363 | end 364 | searchStartingPoint = k + 1; 365 | % store the value to vector C if the variable 366 | % refers to the objective function 367 | if k == objInd 368 | C{clmn} = value; 369 | objectivity = 1; 370 | else 371 | A(k, clmn) = value; % store to matrix A 372 | end 373 | end 374 | end 375 | A(:, 1) = []; 376 | variables(1, :) = []; 377 | [x, ~] = size(variables); 378 | % checking for any mistakes made during the preallocation 379 | % of matrix A 380 | if estimation > x 381 | A(:, x + 1:(estimation - 1)) = []; 382 | end 383 | C(:, 1) = []; 384 | [fr, ~] = size(A); 385 | rflag = 0; 386 | bflag = 0; 387 | % read the RHS section and populate vector b 388 | % stop if the end of the MPS file reached 389 | while isequal(varname, 'ENDATA') == 0 390 | varname = ''; 391 | varpos = ''; 392 | value = ''; 393 | varpos2 = ''; 394 | value2 = ''; 395 | line = fgets(fid); 396 | b = length(line); 397 | % stop if the end of the MPS file reached 398 | if isequal(line(1, 1:6), 'ENDATA') 399 | rflag = 0; 400 | bflag = 0; 401 | break 402 | % stop if we reached the RANGES section 403 | elseif isequal(line(1, 1:6), 'RANGES') 404 | rflag = 1; 405 | break 406 | % stop if we reached the BOUNDS section 407 | elseif isequal(line(1, 1:6), 'BOUNDS') 408 | bflag = 1; 409 | break 410 | end 411 | % read the right-hand side name, the constraint name 412 | % and the value 413 | varname = sscanf(line(1, 5:12), '%s%', 1); 414 | varpos = sscanf(line(1, 15:22), '%s%', 1); 415 | value = sscanf(line(1, 25:b), '%s%', 1); 416 | value = str2double(value); 417 | if b > 40 % if exists the fifth and sixth fields 418 | varpos2 = sscanf(line(1, 40:b), '%s%', 1); 419 | value2 = str2double(line(1, 50:b)); 420 | k2 = strmatch(varpos2, D, 'exact'); 421 | B(k2) = value2; % store the value to vector B 422 | end 423 | k = strmatch(varpos, D, 'exact'); 424 | B(k) = value; % store the value to vector B 425 | end 426 | frb = length(B); 427 | if frb > fr % check if the objective has a constant 428 | B(frb) = []; 429 | end 430 | % read the RANGES section and populate matrix R 431 | if rflag == 1 432 | range_ind = 1; 433 | % stop if the end of the MPS file reached 434 | while isequal(varname, 'ENDATA') == 0 435 | varname = ''; 436 | varpos = ''; 437 | value = ''; 438 | varpos2 = ''; 439 | value2 = ''; 440 | line = fgets(fid); 441 | b = length(line); 442 | % stop if the end of the MPS file reached 443 | if isequal(line(1, 1:6), 'ENDATA') 444 | bflag = 0; 445 | break 446 | % stop if we reached the BOUNDS section 447 | elseif isequal(line(1, 1:6), 'BOUNDS') 448 | bflag = 1; 449 | break 450 | end 451 | % read the range name, the constraint name and 452 | % the value 453 | varname = sscanf(line(1, 5:12), '%s%', 1); 454 | varpos = sscanf(line(1, 15:22), '%s%', 1); 455 | value = sscanf(line(1, 25:b), '%s%', 1); 456 | value = str2double(value); 457 | if b > 40 % if exists the fifth and sixth fields 458 | varpos2 = sscanf(line(1, 40:b), '%s%', 1); 459 | value2 = str2double(line(1, 50:b)); 460 | end 461 | k = strmatch(varpos, D, 'exact'); 462 | R(range_ind, 1) = k; 463 | % store range to matrix R 464 | if isequal(X{k, 1}, 'E') 465 | if value > 0 % Type of row E and sign of the 466 | % range value + 467 | R(range_ind, 2) = B(k); 468 | R(range_ind, 3) = (B(k) + abs(value)); 469 | R(range_ind, 4) = 1; 470 | elseif value < 0 % Type of row E and sign of 471 | % the range value - 472 | R(range_ind, 2) = B(k) - abs(value); 473 | R(range_ind, 3) = B(k); 474 | R(range_ind, 4) = -1; 475 | end 476 | elseif isequal(X{k, 1}, 'L') % Type of row L 477 | R(range_ind, 2) = B(k) - abs(value); 478 | R(range_ind, 3) = B(k); 479 | if value > 0 480 | R(range_ind, 4) = 1; 481 | else 482 | R(range_ind, 4) = -1; 483 | end 484 | elseif isequal(X{k, 1}, 'G') % Type of row G 485 | R(range_ind, 2) = B(k); 486 | R(range_ind, 3) = B(k) + abs(value); 487 | if value > 0 488 | R(range_ind, 4) = 1; 489 | else 490 | R(range_ind, 4) = -1; 491 | end 492 | end 493 | range_ind = range_ind + 1; 494 | k = strmatch(varpos2, D, 'exact'); 495 | if isempty(k) ~= 1 496 | R(range_ind, 1) = k; 497 | % store range to matrix R 498 | if isequal(X{k, 1}, 'E') 499 | if value2 > 0 % Type of row E and sign of 500 | % the range value + 501 | R(range_ind, 2) = B(k); 502 | R(range_ind, 3) = B(k) + abs(value2); 503 | R(range_ind, 4) = 1; 504 | elseif value2 < 0 % Type of row E and sign 505 | % of the range value - 506 | R(range_ind, 2) = B(k) - abs(value2); 507 | R(range_ind, 3) = B(k); 508 | R(range_ind, 4) = -1; 509 | end 510 | elseif isequal(X{k, 1}, 'L') % Type of row L 511 | R(range_ind, 2) = B(k) - abs(value2); 512 | R(range_ind, 3) = B(k); 513 | if value2 > 0 514 | R(range_ind, 4) = 1; 515 | else 516 | R(range_ind, 4) = -1; 517 | end 518 | elseif isequal(X{k, 1}, 'G') % Type of row G 519 | R(range_ind, 2) = B(k); 520 | R(range_ind, 3) = B(k) + abs(value2); 521 | if value2 > 0 522 | R(range_ind, 4) = 1; 523 | else 524 | R(range_ind, 4) = -1; 525 | end 526 | end 527 | range_ind = range_ind + 1; 528 | end 529 | end 530 | end 531 | % read the BOUNDS section and populate matrix BS 532 | if bflag == 1 533 | D = variables(:, 1); 534 | % possible bound types 535 | Types = {'LO' 'UP' 'FX' 'FR' 'MI' 'PL'}; 536 | bound_ind = 1; 537 | while isequal(varname, 'ENDATA') == 0 538 | boundtype = ''; 539 | varname = ''; 540 | value = ''; 541 | line = fgets(fid); 542 | b = length(line); 543 | % stop if the end of the MPS file reached 544 | if isequal(line(1, 1:6), 'ENDATA') 545 | break 546 | end 547 | % read the bound type, the bound name, the 548 | % variable name and the value 549 | boundtype = sscanf(line(1, 2:4), '%s%', 1); 550 | if b > 22 % % LO, UP and FX type of constraints 551 | % have a value field 552 | varname = sscanf(line(1, 15:22), '%s%', 1); 553 | value = sscanf(line(1, 25:b), '%s%', 1); 554 | value = str2double(value); 555 | BS{bound_ind, 3} = value; 556 | else % FR, MI, PL type of constraints do not 557 | % have a value field 558 | varname = sscanf(line(1, 15:b), '%s%', 1); 559 | BS{bound_ind, 3} = NaN; 560 | end 561 | k = strmatch(varname, D, 'exact'); 562 | BS{bound_ind, 1} = k; 563 | k2 = strmatch(boundtype, Types, 'exact'); 564 | if k2 == 1 % LO bound 565 | BS{bound_ind, 2} = 1; 566 | elseif k2 == 2 % UP bound 567 | BS{bound_ind, 2} = -1; 568 | elseif k2 == 3 % FX bound 569 | BS{bound_ind, 2} = 0; 570 | elseif k2 == 4 % FR bound 571 | BS{bound_ind, 2} = 11; 572 | elseif k2 == 5 % MI bound 573 | BS{bound_ind, 2} = 111; 574 | elseif k2 == 6 % MV bound 575 | BS{bound_ind, 2} = 1111; 576 | end 577 | bound_ind = bound_ind + 1; 578 | end 579 | end 580 | c = cell2mat(C); % convert cell to matrix 581 | c = sparse(c'); % transpose and make vector c sparse 582 | % calculate the nonzero elements 583 | NonZeros = nnz(A); 584 | b = sparse(B); % make vector b sparse 585 | A = sparse(A); % make matrix A sparse 586 | R = sparse(R); % make matrix R sparse 587 | BS = cell2mat(BS); % convert cell to mat 588 | BS = sparse(BS); % make matrix BS sparse 589 | Eqin = sparse(Eqin); % make vector Eqin sparse 590 | Name = filename; 591 | % save to file 592 | c0 = 0; 593 | save matlab.mat Name c A b R BS Eqin NonZeros ... 594 | MinMaxLP c0 595 | copyfile('matlab.mat', [filename '.mat']); % copy file 596 | fclose(fid); % close the file 597 | delete matlab.mat % delete matlab.mat 598 | end -------------------------------------------------------------------------------- /codes/chapter3/sparseMenu.m: -------------------------------------------------------------------------------- 1 | function sparseMenu(m, n) 2 | % Filename: sparseMenu.m 3 | % Description: Custom menu for creating sparse random LPs 4 | % Authors: Ploskas, N., & Samaras, N. 5 | % 6 | % Syntax: sparseMenu(m, n) 7 | % 8 | % Input: 9 | % -- m: the number of constraints of the generated random 10 | % LPs 11 | % -- n: the number of variables of the generated random 12 | % LPs 13 | % 14 | % Output: files that store the generated sparse random LPs 15 | 16 | % read the directory to store the LPs 17 | pathName = input(['Please give the path where you ' ... 18 | 'want to store the generated LPs: ']); 19 | % read the number of the LPs to generate 20 | nOfProblems = input(['Please give the number of the ' ... 21 | 'LPs that you want to create: ']); 22 | % read the density of the LPs to generate 23 | dense = input('Please enter the density of the LP: '); 24 | % read the ranges of the values for matrix A 25 | Alu = input(['Please give the range of the values for ' ... 26 | 'matrix A: ']); 27 | % read the ranges of the values for vector c 28 | clu = input(['Please give the range of the values for ' ... 29 | 'vector c: ']); 30 | % read the ranges of the values for vector b 31 | blu = input(['Please give the range of the values for ' ... 32 | 'vector b: ']); 33 | % read the ranges of the values for vector Eqin 34 | Eqinlu = input(['Please give the range of the values ' ... 35 | 'for vector Eqin (0 - equality constraints, 1 - ' ... 36 | 'less than or equal to inequality constraints, ' ... 37 | '2 - greater than or equal to inequality ' ... 38 | 'constraints: ']); 39 | % read the type of optimization 40 | optType = input(['Please give the type of ' ... 41 | 'optimization (0 min, 1 max, 2 random): ']); 42 | % read if all LPs will be optimal 43 | optimality = input(['Do you want all the LPs to be ' ... 44 | 'optimal (1 yes, 2 no): ']); 45 | if optimality == 1 % optimal LPs 46 | % read the lower bound of b1 47 | t1 = input('Please give the lower bound of b1: '); 48 | % read the upper bound of b1 49 | t2 = input('Please give the upper bound of b1: '); 50 | % create nOfProblems sparse random optimal LPs 51 | for i = 1:nOfProblems 52 | [A, c, b, Eqin, MinMaxLP] = ... 53 | sparseRandomOptimal(m, n, optType, Alu, ... 54 | clu, blu, Eqinlu, dense, t1, t2); 55 | s1 = num2str(m); 56 | s2 = num2str(n); 57 | k = num2str(i); 58 | fname = [pathName '/' 'sdata' k '_' s1 'x' s2]; 59 | Name = ['sdata' k '_' s1 'x' s2]; 60 | A = sparse(A); 61 | c = sparse(c); 62 | b = sparse(b); 63 | Eqin = sparse(Eqin); 64 | R = []; 65 | BS = []; 66 | NonZeros = nnz(A); 67 | c0 = 0; 68 | c00 = 0; 69 | eval (['save ' fname '.mat A c b Eqin MinMaxLP ' ... 70 | 'Name R BS NonZeros c0 c00']); 71 | end 72 | else % not optimal LPs 73 | % create nOfProblems sparse random LPs 74 | for i = 1:nOfProblems 75 | [A, c, b, Eqin, MinMaxLP] = sparseRandom(m, n, ... 76 | optType, Alu, clu, blu, Eqinlu, dense); 77 | s1 = num2str(m); 78 | s2 = num2str(n); 79 | k = num2str(i); 80 | fname = [pathName '/' 'sdata' k '_' s1 'x' s2]; 81 | Name = ['sdata' k '_' s1 'x' s2]; 82 | A = sparse(A); 83 | c = sparse(c); 84 | b = sparse(b); 85 | Eqin = sparse(Eqin); 86 | R = []; 87 | BS = []; 88 | NonZeros = nnz(A); 89 | c0 = 0; 90 | c00 = 0; 91 | eval (['save ' fname '.mat A c b Eqin MinMaxLP ' ... 92 | ' Name R BS NonZeros c0 c00']); 93 | end 94 | end 95 | end -------------------------------------------------------------------------------- /codes/chapter3/sparseRandom.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = sparseRandom(m, n, ... 2 | optType, Alu, clu, blu, Eqinlu, dense) 3 | % Filename: sparseRandom.m 4 | % Description: Creates sparse random LPs 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, Eqin, MinMaxLP] = sparseRandom(m, n, ... 8 | % optType, Alu, clu, blu, dense) 9 | % 10 | % Input: 11 | % -- m: the number of constraints of the generated random 12 | % LPs 13 | % -- n: the number of variables of the generated random 14 | % LPs 15 | % -- optType: the type of optimization (0 min, 1 max, 2 16 | % random) 17 | % -- Alu: the ranges of the values for matrix A 18 | % (size 1 x 2) 19 | % -- clu: the ranges of the values for vector c 20 | % (size 1 x 2) 21 | % -- blu: the ranges of the values for vector b 22 | % (size 1 x 2) 23 | % -- Eqinlu: the ranges of the values for vector Eqin 24 | % (size 1 x 2) 25 | % -- dense: the density of matrix A 26 | % 27 | % Output: 28 | % -- A: matrix of coefficients of the constraints 29 | % (size m x n) 30 | % -- c: vector of coefficients of the objective function 31 | % (size n x 1) 32 | % -- b: vector of the right-hand side of the constraints 33 | % (size m x 1) 34 | % -- Eqin: vector of the type of the constraints 35 | % (size m x 1) 36 | % -- MinMaxLP: the type of optimization 37 | 38 | Al = Alu(1); % get the lower bound of A 39 | Au = Alu(2); % get the upper bound of A 40 | % create matrix A 41 | A = round((Au - Al + 1) * sprand(m, n, dense)); 42 | [k, l, s] = find(A); 43 | for i = 1:length(k) 44 | A(k(i), l(i)) = s(i) + Al; 45 | end 46 | cl = clu(1); % get the lower bound of c 47 | cu = clu(2); % get the upper bound of c 48 | % create vector c 49 | c = floor((cu - cl + 1) * rand(n, 1)) + cl; 50 | bl = blu(1); % get the upper bound of b 51 | bu = blu(2); % get the upper bound of b 52 | % create vector b 53 | b = floor((bu - bl + 1) * rand(m, 1)) + bl; 54 | eqinl = Eqinlu(1); % get the lower bound of Eqin 55 | eqinu = Eqinlu(2); % get the upper bound of Eqin 56 | % create vector Eqin 57 | Eqin = floor((eqinu - eqinl + 1) * rand(m, 1)) + eqinl; 58 | % less than or equal to inequality constraints 59 | Eqin(Eqin == 1) = -1; 60 | % greater than or equal to inequality constraints 61 | Eqin(Eqin == 2) = 1; 62 | if optType == 0 % minimization 63 | MinMaxLP = -1; 64 | elseif optType == 1 % maximization 65 | MinMaxLP = 1; 66 | else % pick random optimization type 67 | MinMaxLP = -1; 68 | if randi(2) < 2 69 | MinMaxLP = 1; 70 | end 71 | end 72 | end -------------------------------------------------------------------------------- /codes/chapter3/sparseRandomOptimal.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, MinMaxLP] = ... 2 | sparseRandomOptimal(m, n, optType, Alu, clu, blu, ... 3 | Eqinlu, dense, t1, t2) 4 | % Filename: sparseRandomOptimal.m 5 | % Description: Creates sparse random optimal LPs 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, Eqin, MinMaxLP] = ... 9 | % sparseRandomOptimal(m, n, optType, Alu, clu, blu, ... 10 | % Eqinlu, dense, t1, t2) 11 | % 12 | % Input: 13 | % -- m: the number of constraints of the generated random 14 | % LPs 15 | % -- n: the number of variables of the generated random 16 | % LPs 17 | % -- optType: the type of optimization (0 min, 1 max, 2 18 | % random) 19 | % -- Alu: the ranges of the values for matrix A 20 | % (size 1 x 2) 21 | % -- clu: the ranges of the values for vector c 22 | % (size 1 x 2) 23 | % -- blu: the ranges of the values for vector b 24 | % (size 1 x 2) 25 | % -- Eqinlu: the ranges of the values for vector Eqin 26 | % (size 1 x 2) 27 | % -- dense: the density of matrix A 28 | % -- t1: the lower bound of b1 29 | % -- t2: the upper bound of b1 30 | % 31 | % Output: 32 | % -- A: matrix of coefficients of the constraints 33 | % (size m x n) 34 | % -- c: vector of coefficients of the objective function 35 | % (size n x 1) 36 | % -- b: vector of the right-hand side of the constraints 37 | % (size m x 1) 38 | % -- Eqin: vector of the type of the constraints 39 | % (size m x 1) 40 | % -- MinMaxLP: the type of optimization 41 | 42 | Al = Alu(1); % get the lower bound of A 43 | Au = Alu(2); % get the upper bound of A 44 | % create matrix A 45 | A = round((Au - Al + 1) * sprand(m, n, dense)); 46 | [k, l, s] = find(A); 47 | for i = 1:length(k) 48 | A(k(i), l(i)) = s(i) + Al; 49 | end 50 | cl = clu(1); % get the lower bound of c 51 | cu = clu(2); % get the upper bound of c 52 | % create vector c 53 | c = floor((cu - cl + 1) * rand(n, 1)) + cl; 54 | bl = blu(1); % get the upper bound of b 55 | bu = blu(2); % get the upper bound of c 56 | % create vector b 57 | b = floor((bu - bl + 1) * rand(m, 1)) + bl; 58 | eqinl = Eqinlu(1); % get the lower bound of Eqin 59 | eqinu = Eqinlu(2); % get the upper bound of Eqin 60 | % create vector Eqin 61 | Eqin = floor((eqinu - eqinl + 1) * rand(m, 1)) + eqinl; 62 | if any(Eqin == 1) % increase the value of the less than or 63 | % equal to constraints in order to create artificially 64 | % a closed polyhedron 65 | m_1 = find(Eqin == 1); 66 | m_11 = length(m_1); 67 | b(m_1) = floor((t2 - t1 + 1) * rand(m_11, 1)) + t1; 68 | end 69 | % less than or equal to inequality constraints 70 | Eqin(Eqin == 1) = -1; 71 | % greater than or equal to inequality constraints 72 | Eqin(Eqin == 2) = 1; 73 | if optType == 0 % minimization 74 | MinMaxLP = -1; 75 | elseif optType == 1 % maximization 76 | MinMaxLP = 1; 77 | else % pick random optimization type 78 | MinMaxLP = -1; 79 | if randi(2) < 2 80 | MinMaxLP = 1; 81 | end 82 | end 83 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateDualSingletonInequalityConstraints.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, infeasible] = ... 2 | eliminateDualSingletonInequalityConstraints(A, c, b, Eqin) 3 | % Filename: eliminateDualSingletonInequalityConstraints.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates dual singleton 6 | % inequality constraints 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, infeasible] = ... 10 | % eliminateDualSingletonInequalityConstraints(A, c, b, Eqin) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % 22 | % Output: 23 | % -- A: presolved matrix of coefficients of the constraints 24 | % (size m x n) 25 | % -- c: presolved vector of coefficients of the objective 26 | % function (size n x 1) 27 | % -- b: presolved vector of the right-hand side of the 28 | % constraints (size m x 1) 29 | % -- Eqin: presolved vector of the type of the constraints 30 | % (size m x 1) 31 | % -- infeasible: flag variable showing if the LP is 32 | % infeasible or not 33 | 34 | infeasible = 0; 35 | % compute the number of nonzero elements in each column 36 | delcols = sum(spones(A)); 37 | % find the columns that have only one nonzero element and set 38 | % all the other columns equal to zero 39 | singleton = (delcols == 1); 40 | % find the number of the columns that have only one nonzero 41 | % element 42 | cardcols = nnz(singleton); 43 | countercols = 0; 44 | counterrows = 0; 45 | if cardcols > 0 % if dual singleton constraints exist 46 | % get the indices of the dual singleton constraints 47 | idscols = int16(find(singleton)); 48 | % compute the number of the dual singleton constraints 49 | cardcols = length(idscols); 50 | % for each dual singleton inequality constraint 51 | for j = cardcols:-1:1 52 | jj = idscols(j); % get the index of the constraint 53 | % find the nonzero elements of this column 54 | [row, ~] = find(A(:, jj)); 55 | if ~isempty(row) % if there are nonzero elements 56 | if Eqin(row) == -1 % constraint type <= 57 | % eliminate the dual singleton inequality 58 | % constraints (Case 1) 59 | if (A(row, jj) > 0) && (c(jj) > 0) 60 | A(:, jj) = []; 61 | c(jj) = []; 62 | countercols = countercols + 1; 63 | % check if the LP problem is infeasible 64 | % (Case 2) 65 | elseif (A(row, jj) < 0) && (c(jj) < 0) 66 | infeasible = 1; 67 | return; 68 | % eliminate the dual singleton inequality 69 | % constraints (Case 3) 70 | elseif (A(row,jj) > 0) && (c(jj) == 0) 71 | A(:, jj) = []; 72 | c(jj) = []; 73 | countercols = countercols + 1; 74 | % eliminate the dual singleton inequality 75 | % constraints (Case 4) 76 | elseif (A(row, jj) < 0) && (c(jj) == 0) 77 | A(:, jj) = []; 78 | c(jj) = []; 79 | A(row, :) = []; 80 | b(row) = []; 81 | Eqin(row) = []; 82 | countercols = countercols + 1; 83 | counterrows = counterrows + 1; 84 | end 85 | elseif Eqin(row) == 1 % constraint type >= 86 | % check if the LP problem is unbounded 87 | % (Case 5) 88 | if (A(row, jj) > 0) && (c(jj) < 0) 89 | infeasible = 1; 90 | return; 91 | % eliminate the dual singleton inequality 92 | % constraints (Case 6) 93 | elseif (A(row, jj) < 0) && (c(jj) > 0) 94 | A(:, jj) = []; 95 | c(jj) = []; 96 | countercols = countercols + 1; 97 | % eliminate the dual singleton inequality 98 | % constraints (Case 7) 99 | elseif (A(row,jj) > 0) && (c(jj) == 0) 100 | A(:, jj) = []; 101 | c(jj) = []; 102 | A(row, :) = []; 103 | b(row) = []; 104 | Eqin(row) = []; 105 | countercols = countercols + 1; 106 | counterrows = counterrows + 1; 107 | % eliminate the dual singleton inequality 108 | % constraints (Case 8) 109 | elseif (A(row, jj) < 0) && (c(jj) == 0) 110 | A(:, jj) = []; 111 | c(jj) = []; 112 | countercols = countercols + 1; 113 | end 114 | end 115 | end 116 | end 117 | if (countercols > 0) || (counterrows > 0) 118 | fprintf(['ELIMINATE DUAL SINGLETON INEQUALITY ' ... 119 | 'CONSTRAINTS: %i constraints and %i columns ' ... 120 | 'were eliminated\n'], counterrows, ... 121 | countercols); 122 | end 123 | end 124 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateImpliedBoundsonRows.m: -------------------------------------------------------------------------------- 1 | function [A, b, Eqin] = eliminateImpliedBoundsonRows(A, ... 2 | b, Eqin) 3 | % Filename: eliminateImpliedBoundsonRows.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates implied bounds on 6 | % rows 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, b, Eqin] = eliminateImpliedBoundsonRows(A, ... 10 | % b, Eqin) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % -- Eqin: vector of the type of the constraints 18 | % (size m x 1) 19 | % 20 | % Output: 21 | % -- A: presolved matrix of coefficients of the constraints 22 | % (size m x n) 23 | % -- b: presolved vector of the right-hand side of the 24 | % constraints (size m x 1) 25 | % -- Eqin: presolved vector of the type of the constraints 26 | % (size m x 1) 27 | 28 | [row, ~] = find(Eqin ~= 0); % find the inequality constraints 29 | % find the number of these constraints 30 | cardrows = length(row); 31 | counterrows = 0; 32 | for i = cardrows:-1:1 % for each of these constraints 33 | ii = row(i); % get the index of the constraint 34 | % if all elements in that constraint are less than or 35 | % equal to zero, the constraint has a right-hand side 36 | % greater than or equal to zero, and the constraint 37 | % type is <=, then eliminate the constraint and update 38 | % matrix A and vectors b and Eqin (Case 1) 39 | if all((A(ii, :) <= 0)) && (b(ii) >= 0) 40 | if Eqin(ii) == -1 41 | A(ii, :) = []; 42 | Eqin(ii) = []; 43 | b(ii) = []; 44 | counterrows = counterrows + 1; 45 | end 46 | % if all elements in that constraint are greater than 47 | % or equal to zero, the constraint has a right-hand 48 | % side less than or equal to zero, and the constraint 49 | % type is >=, then eliminate the constraint and update 50 | % matrix A and vectors b and Eqin (Case 1) 51 | elseif all((A(ii, :) >= 0)) && (b(ii) <= 0) 52 | if Eqin(ii) == 1 53 | A(ii, :) = []; 54 | Eqin(ii) = []; 55 | b(ii) = []; 56 | counterrows = counterrows + 1; 57 | end 58 | end 59 | end 60 | if counterrows > 0 61 | fprintf(['ELIMINATE IMPLIED BOUNDS ON ROWS: %i ' ... 62 | 'constraints were eliminated\n'], counterrows); 63 | end 64 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateImpliedFreeSingletonColumns.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, c0] = ... 2 | eliminateImpliedFreeSingletonColumns(A, c, b, Eqin, c0) 3 | % Filename: eliminateImpliedFreeSingletonColumns.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates implied free 6 | % singleton constraints 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, c0] = ... 10 | % eliminateImpliedFreeSingletonColumns(A, c, b, Eqin, c0) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- c0: constant term of the objective function 22 | % 23 | % Output: 24 | % -- A: presolved matrix of coefficients of the constraints 25 | % (size m x n) 26 | % -- c: presolved vector of coefficients of the objective 27 | % function (size n x 1) 28 | % -- b: presolved vector of the right-hand side of the 29 | % constraints (size m x 1) 30 | % -- Eqin: presolved vector of the type of the constraints 31 | % (size m x 1) 32 | % -- c0: updated constant term of the objective function 33 | 34 | % compute the number of nonzero elements in each column 35 | delcols = sum(spones(A)); 36 | % find the columns that have only one nonzero element and 37 | % set all the other columns equal to zero 38 | singleton = (delcols == 1); 39 | % find the number of the columns that have only one nonzero 40 | % element 41 | cardcols = nnz(singleton); 42 | idscols = find(singleton); 43 | countercols = 0; 44 | for j = cardcols:-1:1 % for each dual singleton constraint 45 | jj = idscols(j); % get the index of the constraint 46 | % find the nonzero elements of this column 47 | [row, ~] = find(A(:, jj)); 48 | if ~isempty(row) % if there are nonzero elements 49 | if Eqin(row) == 0 % constraint type = 50 | % if the element is greater than zero 51 | if A(row, jj) > 0 52 | % find the number of columns 53 | n0 = size(A, 2); 54 | % compute the indices of all other columns 55 | set = setdiff(1:n0, jj); 56 | % if all the elements of the row except 57 | % the one in the specific column are less 58 | % than or equal to zero and the right-hand 59 | % side greater than or equal to zero, 60 | % then update matrix A, vectors c, b, and 61 | % Eqin, and variable c0 62 | if all(A(row, set) <= 0) && b(row) >= 0 63 | if c(jj) ~= 0 64 | c0 = c0 + c(jj) * (b(row) / A(row, jj)); 65 | c = c - (c(jj) / A(row, jj)) * A(row, :)'; 66 | end 67 | c(jj) = []; 68 | A(:, jj) = []; 69 | A(row, :) = []; 70 | b(row) = []; 71 | Eqin(row) = []; 72 | countercols = countercols + 1; 73 | end 74 | elseif A(row, jj) < 0 % if the element is less 75 | % than zero 76 | n0 = size(A, 2); % find the number of columns 77 | % compute the indices of all other columns 78 | set = setdiff(1:n0, jj); 79 | % if all the elements of the row except the 80 | % one in the specific column are greater than 81 | % or equal to zero and the right-hand side 82 | % less than or equal to zero, then update 83 | % matrix A, vectors c, b, and Eqin, and 84 | % variable c0 85 | if all(A(row, set) >= 0) && b(row) <= 0 86 | if c(jj) ~= 0 87 | c0 = c0 + c(jj) * (b(row) / A(row, jj)); 88 | c = c - (c(jj) / A(row,jj)) * A(row, :)'; 89 | end 90 | c(jj) = []; 91 | A(:, jj) = []; 92 | A(row, :) = []; 93 | b(row) = []; 94 | Eqin(row) = []; 95 | countercols = countercols + 1; 96 | end 97 | end 98 | elseif Eqin(row) == 1 % constraint type <= 99 | if A(row, jj) > 0 % if the element is greater 100 | % than zero 101 | n0 = size(A, 2); % find the number of columns 102 | % compute the indices of all other columns 103 | set = setdiff(1:n0, jj); 104 | % if all the elements of the row except 105 | % the one in the specific column are less 106 | % than or equal to zero and the right-hand 107 | % side greater than or equal to -1, then 108 | % update matrix A, vectors c, b, and Eqin, and 109 | % variable c0 110 | if all(A(row, set) <= 0) && b(row) >= -1 111 | if c(jj) ~= 0 112 | c0 = c0 + c(jj) * (b(row) ... 113 | / A(row, jj)); 114 | c = c - (c(jj) / A(row, jj)) ... 115 | * A(row, :)'; 116 | end 117 | c(jj) = []; 118 | A(:, jj) = []; 119 | A(row, :) = []; 120 | b(row) = []; 121 | Eqin(row) = []; 122 | countercols = countercols + 1; 123 | end 124 | end 125 | elseif Eqin(row) == -1 % constraint type >= 126 | if A(row, jj) < 0 % if the element is less 127 | % than zero 128 | n0 = size(A, 2); % find the number of columns 129 | % compute the indices of all other columns 130 | set = setdiff(1:n0, jj); 131 | % if all the elements of the row except 132 | % the one in the specific column are greater 133 | % than or equal to zero and the right-hand 134 | % side less than or equal to 1, then update 135 | % matrix A, vectors c, b, and Eqin, and 136 | % variable c0 137 | if all(A(row, set) >= 0) && b(row) <= 1 138 | if c(jj) ~= 0 139 | c0 = c0 + c(jj) * (b(row) ... 140 | / A(row, jj)); 141 | c = c - (c(jj) / A(row, jj)) ... 142 | * A(row, :)'; 143 | end 144 | c(jj) = []; 145 | A(:, jj) = []; 146 | A(row, :) = []; 147 | b(row) = []; 148 | Eqin(row) = []; 149 | countercols = countercols + 1; 150 | end 151 | end 152 | end 153 | end 154 | end 155 | if countercols > 0 156 | fprintf(['ELIMINATE IMPLIED FREE SINGLETON COLUMNS: ' ... 157 | '%i rows and %i columns were eliminated\n'], ... 158 | countercols, countercols); 159 | end 160 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateKtonEqualityConstraints.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, c0, infeasible] = ... 2 | eliminateKtonEqualityConstraints(A, c, b, Eqin, ... 3 | c0, kton) 4 | % Filename: eliminateKtonEqualityConstraints.m 5 | % Description: the function is an implementation of the 6 | % presolve technique that eliminates kton equality 7 | % constraints 8 | % Authors: Ploskas, N., & Samaras, N. 9 | % 10 | % Syntax: [A, c, b, Eqin, c0, infeasible] = ... 11 | % eliminateKtonEqualityConstraints(A, c, b, Eqin, ... 12 | % c0, kton) 13 | % 14 | % Input: 15 | % -- A: matrix of coefficients of the constraints 16 | % (size m x n) 17 | % -- c: vector of coefficients of the objective function 18 | % (size n x 1) 19 | % -- b: vector of the right-hand side of the constraints 20 | % (size m x 1) 21 | % -- Eqin: vector of the type of the constraints 22 | % (size m x 1) 23 | % -- c0: constant term of the objective function 24 | % -- kton: the type of equality constraints to eliminate (1: 25 | % singleton, 2: doubleton, etc.) 26 | % 27 | % Output: 28 | % -- A: presolved matrix of coefficients of the constraints 29 | % (size m x n) 30 | % -- c: presolved vector of coefficients of the objective 31 | % function (size n x 1) 32 | % -- b: presolved vector of the right-hand side of the 33 | % constraints (size m x 1) 34 | % -- Eqin: presolved vector of the type of the constraints 35 | % (size m x 1) 36 | % -- c0: updated constant term of the objective function 37 | % -- infeasible: flag variable showing if the LP is 38 | % infeasible or not 39 | 40 | if kton == 1 41 | [A, c, b, Eqin, c0, infeasible] = ... 42 | eliminateSingletonEqualityConstraints(A, c, b, Eqin, c0); 43 | else 44 | infeasible = 0; 45 | [m, n] = size(A); 46 | tol = max(m, n) * eps * norm(A, 'inf'); % compute tolerance 47 | colindex = sparse(1, n); 48 | ci = 1; 49 | eliminatedRows = 0; 50 | for k = kton:-1:1 % for each k, 1 <= k <= kton 51 | % compute the number of nonzero elements in each row 52 | delrows = sum(spones(A')); 53 | % find the rows that have only k nonzero elements and 54 | % set all the other rows equal to zero 55 | singleton = (delrows == k); 56 | % find the number of the rows that have only k 57 | % nonzero elements 58 | cardrows = nnz(singleton); 59 | % if kton rows exist 60 | if cardrows >= max(1, .01 * size(A, 1)) 61 | % get the indices of the kton rows 62 | idsrows = int16(find(singleton)); 63 | % find equality constraints 64 | [row , ~] = find(Eqin == 0); 65 | % compute the indices of the kton equality 66 | % constraints 67 | idsrows = intersect(idsrows, row); 68 | % compute the number of the kton equality 69 | % constraints 70 | cardrows = length(idsrows); 71 | % for each kton equality constraint 72 | for i = cardrows:-1:1 73 | % get the index of the constraint 74 | ii = idsrows(i); 75 | % find the nonzero elements of this row 76 | [~, j] = find(A(ii, :)); 77 | % find the column of the last nonzero element 78 | if length(j) > 1 79 | j = j(length(j)); 80 | elseif isempty(j) 81 | continue; 82 | end 83 | % set to zero if the value is less than or 84 | % equal to tol and continue to the next 85 | % constraint 86 | if abs(A(ii, j)) <= tol 87 | A(ii, j) = 0; 88 | continue; 89 | else % update matrix A and vectors c, b, 90 | % and Eqin 91 | b(ii) = b(ii) / A(ii, j); 92 | A(ii, :) = A(ii, :) / A(ii, j); 93 | i_nz = find(A(:, j)); 94 | i_nz = setdiff(i_nz, ii); 95 | if ~isempty(i_nz) 96 | for t = i_nz 97 | if b(ii) ~= 0 98 | b(t) = b(t) - A(t, j) * b(ii); 99 | end 100 | A(t, :) = A(t, :) - A(t, j) * A(ii, :); 101 | Eqin(ii) = -1; 102 | colindex(ci) = j; 103 | ci = ci + 1; 104 | end 105 | else 106 | Eqin(ii) = -1; 107 | colindex(ci) = j; 108 | ci = ci + 1; 109 | end 110 | if c(j) ~= 0 111 | c0 = c0 + c(j) * b(ii); 112 | c = c - c(j) * A(ii, :)'; 113 | end 114 | % the LP problem is infeasible (Case 2) 115 | if (k == 1) && (b(ii) < 0) 116 | infeasible = 1; 117 | return; 118 | end 119 | if (k == 1) && (b(ii) >= 0) 120 | % delete the iith constraint 121 | A(ii, :) = []; 122 | b(ii) = []; 123 | Eqin(ii) = []; 124 | eliminatedRows = eliminatedRows + 1; 125 | end 126 | end 127 | end 128 | end 129 | end 130 | colindex = sort(colindex, 'descend'); 131 | cardcols = nnz(colindex); 132 | if cardcols > 0 % delete variables 133 | for j = 1:cardcols 134 | A(:, colindex(j)) = []; 135 | c(colindex(j)) = []; 136 | end 137 | end 138 | if (eliminatedRows > 0) || (cardcols > 0) 139 | fprintf(['ELIMINATE KTON EQUALITY CONSTRAINTS: ' ... 140 | '%i kton equality constraints were ' ... 141 | 'found. %i constraints and %i variables were ' ... 142 | 'eliminated\n'], cardcols, eliminatedRows, cardcols); 143 | end 144 | end 145 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateRedundantColumns.m: -------------------------------------------------------------------------------- 1 | function [A, c] = eliminateRedundantColumns(A, c, b, Eqin) 2 | % Filename: eliminateRedundantColumns.m 3 | % Description: the function is an implementation of the 4 | % presolve technique that eliminates redundant columns 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c] = eliminateRedundantColumns(A, c, b, Eqin) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- c: vector of coefficients of the objective function 13 | % (size n x 1) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % -- Eqin: vector of the type of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: presolved matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: presolved vector of coefficients of the objective 23 | % function (size n x 1) 24 | 25 | [row, ~] = find(Eqin == 0); % find the equality constraints 26 | % find the constraints with a zero right-hand side 27 | [row1, ~] = find(b == 0); 28 | % get the intersection of these sets, i.e., the equality 29 | % constraints with a zero right-hand side 30 | idsrows = intersect(row, row1); 31 | % find the number of these constraints 32 | cardrows = length(idsrows); 33 | countercols = 0; 34 | if cardrows > 0 % if such constraints exist 35 | for i = cardrows:-1:1 % for each of these constraints 36 | ii = idsrows(i); % get the index of the constraint 37 | % find the nonzero elements of this row 38 | [row, j] = find(A(ii, :)); 39 | if ~isempty(row) % if there are nonzero elements 40 | % if all elements are greater than zero, 41 | % eliminate the columns and update matrix A 42 | % and vector c 43 | if all(A(ii, j) > 0) 44 | c(j) = []; 45 | A(:, j) = []; 46 | countercols = countercols + length(j); 47 | % if all elements are less than zero, eliminate 48 | % the columns and update matrix A and vector c 49 | elseif all(A(ii, j) < 0) 50 | c(j) = []; 51 | A(:, j) = []; 52 | countercols = countercols + length(j); 53 | end 54 | end 55 | end 56 | if countercols > 0 57 | fprintf(['ELIMINATE REDUNDANT COLUMNS: %i ' ... 58 | 'redundant columns were eliminated' ... 59 | '\n'], countercols); 60 | end 61 | end 62 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateRedundantRows.m: -------------------------------------------------------------------------------- 1 | function [A, b, Eqin, infeasible] = ... 2 | eliminateRedundantRows(A, b, Eqin) 3 | % Filename: eliminateRedundantRows.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates redundant rows 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, b, Eqin, infeasible] = ... 9 | % eliminateRedundantRows(A, b, Eqin) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % -- Eqin: vector of the type of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: presolved matrix of coefficients of the 21 | % constraints (size m x n) 22 | % -- b: presolved vector of the right-hand side of the 23 | % constraints (size m x 1) 24 | % -- Eqin: presolved vector of the type of the 25 | % constraints (size m x 1) 26 | % -- infeasible: flag variable showing if the LP problem 27 | % is infeasible or not 28 | 29 | infeasible = 0; 30 | row = find(Eqin == 0); % find the equality constraints 31 | % get the rows of A that correspond to equality 32 | % constraints 33 | Aeqin = A(row, :); 34 | % get the elements of b that correspond to equality 35 | % constraints 36 | beqin = b(row, :); 37 | % find the number of the equality constraints 38 | [m1, n] = size(Aeqin); 39 | % create a 2 x m1 zero matrix 40 | rowindex = zeros(2, m1); 41 | % store the indices of the equality constraints in the 42 | % first row 43 | rowindex(1, 1:m1) = row'; 44 | % compute the tolerance 45 | tol = max(m1, n) * eps * norm(A, 'inf'); 46 | i = 1; 47 | j = 1; 48 | % perform row operations using Gauss - Jordan elimination 49 | % with partial pivoting 50 | while (i <= m1) && (j <= n) 51 | % find the maximum element of jth column of Aeqin in 52 | % absolute value 53 | [p, k] = max(abs(Aeqin(i:m1, j))); 54 | % if the maximum element is less than tol, then set 55 | % all the elements of jth column equal to zero 56 | if p < tol 57 | Aeqin(i:m1, j) = zeros(m1 - i + 1, 1); 58 | j = j + 1; 59 | % perform the pivoting operation and update matrix 60 | % Aeqin and vector beqin 61 | else 62 | if p ~= 0 63 | k = k + i - 1; 64 | rowindex(:, [i k]) = rowindex(:, [k i]); 65 | beqin(i, :) = beqin(i, :) / Aeqin(i, j); 66 | Aeqin(i, j:n) = Aeqin(i, j:n) / Aeqin(i, j); 67 | i_nz = find(Aeqin(:, j)); 68 | i_nz = setdiff(i_nz, i); 69 | for t = i_nz 70 | if beqin(i) ~= 0 71 | beqin(t) = beqin(t) - ... 72 | Aeqin(t, j) * beqin(i); 73 | toler = abs(beqin) <= tol; 74 | beqin(toler == 1) = 0; 75 | end 76 | Aeqin(t, j:n) = Aeqin(t, j:n) ... 77 | - Aeqin(t, j) * Aeqin(i, j:n); 78 | toler = abs(Aeqin) <= tol; 79 | Aeqin(toler == 1) = 0; 80 | end 81 | i = i + 1; 82 | j = j + 1; 83 | end 84 | end 85 | end 86 | i = 1; 87 | for h = [1:i - 1 i + 1:m1] 88 | % if all elements of row h are equal to zero and the 89 | % corresponding right-hand side is equal to 0, then 90 | % row h is redundant and can be deleted 91 | if (Aeqin(h, :) == 0) & (beqin(h) == 0) 92 | rowindex(2, h) = 1; 93 | end 94 | % if all elements of row h are equal to zero and the 95 | % corresponding right-hand side is not equal to 0, 96 | % then the LP problem is infeasible 97 | if (Aeqin(h, :) == 0) & (beqin(h) ~= 0) 98 | infeasible = 1; 99 | return; 100 | end 101 | end 102 | % find the rows that have been marked with 1 103 | if any(rowindex(2, :) == 1) 104 | row = find(rowindex(2, :) == 1); 105 | end 106 | row = (rowindex(2, :) == 1); 107 | row = rowindex(1, row); 108 | row = sort(row); 109 | % find the number of the rows that have been marked with 1 110 | cardrows = length(row); 111 | if cardrows > 0 % if such rows exist 112 | % eliminate these rows and update matrix A and vectors 113 | % b and Eqin 114 | for i = cardrows:-1:1 115 | ii = row(i); 116 | A(ii, :) = []; 117 | b(ii) = []; 118 | Eqin(ii) = []; 119 | end 120 | fprintf(['ELIMINATE REDUNDANT ROWS: %i redundant ' ... 121 | 'rows were eliminated\n'], cardrows); 122 | end 123 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateSingletonEqualityConstraints.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, c0, infeasible] = ... 2 | eliminateSingletonEqualityConstraints(A, c, b, Eqin, c0) 3 | % Filename: eliminateSingletonEqualityConstraints.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates singleton equality 6 | % constraints 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, c0, infeasible] = ... 10 | % eliminateSingletonEqualityConstraints(A, c, b, Eqin, c0) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % -- c0: constant term of the objective function 22 | % 23 | % Output: 24 | % -- A: presolved matrix of coefficients of the constraints 25 | % (size m x n) 26 | % -- c: presolved vector of coefficients of the objective 27 | % function (size n x 1) 28 | % -- b: presolved vector of the right-hand side of the 29 | % constraints (size m x 1) 30 | % -- Eqin: presolved vector of the type of the constraints 31 | % (size m x 1) 32 | % -- c0: updated constant term of the objective function 33 | % -- infeasible: flag variable showing if the LP is 34 | % infeasible or not 35 | 36 | infeasible = 0; 37 | % compute the number of nonzero elements in each row 38 | delrows = sum(spones(A')); 39 | % find the rows that have only one nonzero element and set 40 | % all the other rows equal to zero 41 | singleton = (delrows == 1); 42 | % find the number of the rows that have only one nonzero 43 | % element 44 | cardrows = nnz(singleton); 45 | if cardrows > 0 % if singleton rows exist 46 | % get the indices of the singleton rows 47 | idsrows = int16(find(singleton)); 48 | % find equality constraints 49 | [row, ~] = find(Eqin == 0); 50 | % compute the indices of the singleton equality 51 | % constraints 52 | idsrows = intersect(idsrows, row); 53 | % compute the number of the singleton equality 54 | % constraints 55 | cardrows = length(idsrows); 56 | % for each singleton equality constraint 57 | for i = cardrows:-1:1 58 | ii = idsrows(i); % get the index of the constraint 59 | % find the nonzero elements of this row 60 | [row1, j] = find(A(ii, :)); 61 | if ~isempty(row1) % if there are nonzero elements 62 | b(ii) = b(ii) / A(ii, j); % update b 63 | % if b is greater than or equal to zero 64 | if b(ii) >= 0 65 | b_temp = b(ii) .* A(:, j); 66 | A(:, j) = []; % delete column from A 67 | if c(j) ~= 0 % update c and c0 68 | c(j) = c(j) * b(ii); 69 | c0 = c0 - c(j); 70 | end 71 | % update matrix A and vectors c, b, and Eqin 72 | c(j) = []; 73 | b = b - b_temp; 74 | A(ii, :) = []; 75 | b(ii) = []; 76 | Eqin(ii) = []; 77 | else % the LP problem is infeasible (Case 2) 78 | infeasible = 1; 79 | return; 80 | end 81 | end 82 | end 83 | fprintf(['ELIMINATE SINGLETON EQUALITY CONSTRAINTS: ' ... 84 | '%i singleton equality constraints were ' .... 85 | 'eliminated\n'], cardrows); 86 | end 87 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateSingletonInequalityConstraints.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, infeasible] = ... 2 | eliminateSingletonInequalityConstraints(A, c, b, Eqin) 3 | % Filename: eliminateSingletonInequalityConstraints.m 4 | % Description: the function is an implementation of the 5 | % presolve technique that eliminates singleton 6 | % inequality constraints 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [A, c, b, Eqin, infeasible] = ... 10 | % eliminateSingletonInequalityConstraints(A, c, b, Eqin) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- b: vector of the right-hand side of the constraints 18 | % (size m x 1) 19 | % -- Eqin: vector of the type of the constraints 20 | % (size m x 1) 21 | % 22 | % Output: 23 | % -- A: presolved matrix of coefficients of the constraints 24 | % (size m x n) 25 | % -- c: presolved vector of coefficients of the objective 26 | % function (size n x 1) 27 | % -- b: presolved vector of the right-hand side of the 28 | % constraints (size m x 1) 29 | % -- Eqin: presolved vector of the type of the constraints 30 | % (size m x 1) 31 | % -- infeasible: flag variable showing if the LP is 32 | % infeasible or not 33 | 34 | infeasible = 0; 35 | % compute the number of nonzero elements in each row 36 | delrows = sum(spones(A')); 37 | % find the rows that have only one nonzero element and set 38 | % all the other rows equal to zero 39 | singleton = (delrows == 1); 40 | % find the number of the rows that have only one nonzero 41 | % element 42 | cardrows = nnz(singleton); 43 | counterrows = 0; 44 | countercols = 0; 45 | if cardrows > 0 % if singleton rows exist 46 | % get the indices of the singleton rows 47 | idsrows = int16(find(singleton)); 48 | % find inequality constraints 49 | [row, ~] = find(Eqin ~= 0); 50 | % compute the indices of the singleton inequality 51 | % constraints 52 | idsrows = intersect(idsrows, row); 53 | % compute the number of the singleton inequality 54 | % constraints 55 | cardrows = length(idsrows); 56 | % for each singleton inequality constraint 57 | for i = cardrows:-1:1 58 | ii = idsrows(i); % get the index of the constraint 59 | % find the nonzero elements of this row 60 | [row1, j] = find(A(ii, :)); 61 | if ~isempty(row1) % if there are nonzero elements 62 | if Eqin(ii) == -1 % constraint type <= 63 | % check if the LP problem is infeasible 64 | % (Case 1) 65 | if (A(ii, j) > 0) && (b(ii) < 0) 66 | infeasible = 1; 67 | return; 68 | % eliminate the singleton inequality constraints 69 | % (Case 2) 70 | elseif (A(ii, j) < 0) && (b(ii) > 0) 71 | A(ii, :) = []; 72 | b(ii) = []; 73 | Eqin(ii) = []; 74 | counterrows = counterrows + 1; 75 | % eliminate the singleton inequality constraints 76 | % (Case 3) 77 | elseif (A(ii, j) > 0) && (b(ii) == 0) 78 | A(ii, :) = []; 79 | b(ii) = []; 80 | Eqin(ii) = []; 81 | c(j) = []; 82 | A(:, j) = []; 83 | counterrows = counterrows + 1; 84 | countercols = countercols + 1; 85 | % eliminate the singleton inequality constraints 86 | % (Case 4) 87 | elseif (A(ii, j) < 0) && (b(ii) == 0) 88 | A(ii, :) = []; 89 | b(ii) = []; 90 | Eqin(ii) = []; 91 | counterrows = counterrows + 1; 92 | end 93 | elseif Eqin(ii) == 1 % constraint type >= 94 | % eliminate the singleton inequality constraints 95 | % (Case 5) 96 | if((A(ii, j) > 0) && (b(ii) < 0)) 97 | A(ii, :) = []; 98 | b(ii) = []; 99 | Eqin(ii) = []; 100 | counterrows = counterrows + 1; 101 | % check if the LP problem is infeasible 102 | % (Case 6) 103 | elseif (A(ii, j) < 0) && (b(ii) > 0) 104 | infeasible = 1; 105 | return; 106 | % eliminate the singleton inequality constraints 107 | % (Case 7) 108 | elseif (A(ii, j) > 0) && (b(ii) == 0) 109 | A(ii, :) = []; 110 | b(ii) = []; 111 | Eqin(ii) = []; 112 | counterrows = counterrows + 1; 113 | % eliminate the singleton inequality constraints 114 | % (Case 8) 115 | elseif (A(ii,j) < 0) && (b(ii) == 0) 116 | A(ii, :) = []; 117 | b(ii) = []; 118 | Eqin(ii) = []; 119 | c(j) = []; 120 | A(:, j) = []; 121 | counterrows = counterrows + 1; 122 | countercols = countercols + 1; 123 | end 124 | end 125 | end 126 | end 127 | if (counterrows ~= 0) || (countercols ~= 0) 128 | fprintf(['ELIMINATE SINGLETON INEQUALITY CONSTRAINTS: ' ... 129 | '%i singleton inequality constraints were found. ' ... 130 | '%i constraints and %i variables were eliminated ' ... 131 | '\n'], cardrows, counterrows, countercols); 132 | end 133 | end 134 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateZeroColumns.m: -------------------------------------------------------------------------------- 1 | function [A, c, unbounded] = eliminateZeroColumns(A, c) 2 | % Filename: eliminateZeroColumns.m 3 | % Description: the function is an implementation of the 4 | % presolve method that eliminates zero columns 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, unbounded] = eliminateZeroColumns(A, c) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- c: vector of coefficients of the objective function 13 | % (size n x 1) 14 | % 15 | % Output: 16 | % -- A: presolved matrix of coefficients of the constraints 17 | % (size m x n) 18 | % -- c: presolved vector of coefficients of the objective 19 | % function (size n x 1) 20 | % -- unbounded: flag variable showing if the LP is unbounded 21 | % or not 22 | 23 | unbounded = 0; 24 | % find the columns that have all their elements equal to zero 25 | delcols = (max(abs(A)) == 0)'; 26 | % if any column has all its element equal to zero 27 | if any(delcols == 1) 28 | % get the indices of all columns that have all their 29 | % elements equal to zero 30 | idelcols = int16(find(delcols)); 31 | % check if the LP problem is infeasible (Case 2) 32 | if any(c(idelcols) < 0) 33 | unbounded = 1; 34 | return; 35 | end 36 | % get the indices of all columns that have at least one 37 | % nonzero element 38 | idnnz = int16(find(1 - delcols)); 39 | % update matrix A and vector c by deleting zero columns 40 | A = A(:, idnnz); 41 | c = c(idnnz); 42 | fprintf(['ELIMINATE ZERO COLUMNS: %i zero columns ' ... 43 | 'were eliminated\n'], nnz(delcols)) 44 | end 45 | end -------------------------------------------------------------------------------- /codes/chapter4/eliminateZeroRows.m: -------------------------------------------------------------------------------- 1 | function [A, b, Eqin, infeasible] = ... 2 | eliminateZeroRows(A, b, Eqin) 3 | % Filename: eliminateZeroRows.m 4 | % Description: the function is an implementation of the 5 | % presolve method that eliminates zero rows 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, b, Eqin, infeasible] = ... 9 | % eliminateZeroRows(A, b, Eqin) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % -- Eqin: vector of the type of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: presolved matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- b: presolved vector of the right-hand side of the 23 | % constraints (size m x 1) 24 | % -- Eqin: presolved vector of the type of the constraints 25 | % (size m x 1) 26 | % -- infeasible: flag variable showing if the LP is 27 | % infeasible or not 28 | 29 | infeasible = 0; 30 | % compute the number of nonzero elements in each row 31 | delrows = sum(spones(A')); 32 | % if any row has all its element equal to zero 33 | if any(delrows == 0) 34 | % get the indices of all rows that have all their 35 | % elements equal to zero 36 | id = int16(find(delrows == 0)); 37 | % check if the LP problem is infeasible (Case 2) 38 | k = int16(find(Eqin(id) == -1)); 39 | if any(b(id(k)) < 0) && ~isempty(k) 40 | infeasible = 1; 41 | return; 42 | else 43 | % check if the LP problem is infeasible (Case 4) 44 | k = int16(find(Eqin(id) == 1)); 45 | if any(b(id(k)) > 0) && ~isempty(k) 46 | infeasible = 1; 47 | return; 48 | else 49 | % check if the LP problem is infeasible (Case 6) 50 | k = int16(find(Eqin(id) == 0)); 51 | if any(b(id(k)) ~= 0) && ~isempty(k) 52 | infeasible = 1; 53 | return; 54 | end 55 | end 56 | end 57 | % find the indices of the nonzero rows 58 | idnnz = int16(find(delrows > 0)); 59 | % update matrix A and vectors b and Eqin by deleting 60 | % zero rows 61 | A = A(idnnz, :); 62 | b = b(idnnz); 63 | Eqin = Eqin(idnnz); 64 | fprintf(['ELIMINATE ZERO ROWS: %i zero-rows were ' ... 65 | 'eliminated\n'], length(id)) 66 | end 67 | end -------------------------------------------------------------------------------- /codes/chapter4/fullRank.m: -------------------------------------------------------------------------------- 1 | function [A, b, Eqin] = fullRank(A, Atemp, b, Eqin) 2 | % Filename: fullRank.m 3 | % Description: the function is an implementation of the 4 | % presolve technique that makes the coefficient matrix 5 | % structurally full rank 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, b, Eqin] = fullRank(A, Atemp, b, Eqin) 9 | % 10 | % Input: 11 | % -- A: matrix of coefficients of the constraints before 12 | % adding slack variables (size m x n) 13 | % -- Atemp: matrix of coefficients of the constraints after 14 | % adding slack variables (depending on the type of the 15 | % constraints: if all constraints are equalities then 16 | % Atemp = A and the size of Atemp = m x n, if all 17 | % constraints are inequalities then the size of Atemp 18 | % = m x (m + n)) 19 | % -- b: vector of the right-hand side of the constraints 20 | % (size m x 1) 21 | % -- Eqin: vector of the type of the constraints 22 | % (size m x 1) 23 | % 24 | % Output: 25 | % -- A: presolved matrix of coefficients of the constraints 26 | % (size m x n) 27 | % -- b: presolved vector of the right-hand side of the 28 | % constraints (size m x 1) 29 | % -- Eqin: presolved vector of the type of the constraints 30 | % (size m x 1) 31 | 32 | sp_rank = sprank(Atemp'); % find the rank of matrix Atemp 33 | [m, n] = size(Atemp); % size of Atemp 34 | t = min(m, n); 35 | if sp_rank < t % if the matrix is not of full rank 36 | [rmp, ~] = dmperm(Atemp); 37 | rows = rmp(1:sp_rank); 38 | A = A(rows, :); 39 | b = b(rows); 40 | Eqin = Eqin(rows); 41 | fprintf(['MAKE COEFFICIENT MATRIX STRUCTURALLY FULL ' ... 42 | 'RANK: %i rows were eliminated\n'], t - sp_rank); 43 | end 44 | end -------------------------------------------------------------------------------- /codes/chapter4/presolve.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, Eqin, c0, infeasible, unbounded] = ... 2 | presolve(A, c, b, Eqin, c0) 3 | % Filename: presolve.m 4 | % Description: the function is an implementation of the 5 | % main file that calls all the presolve techniques 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, Eqin, c0, infeasible, unbounded] = ... 9 | % presolve(A, c, b, Eqin, c0) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % -- Eqin: vector of the type of the constraints 19 | % (size m x 1) 20 | % -- c0: constant term of the objective function 21 | % 22 | % Output: 23 | % -- A: presolved matrix of coefficients of the constraints 24 | % (size m x n) 25 | % -- c: presolved vector of coefficients of the objective 26 | % function (size n x 1) 27 | % -- b: presolved vector of the right-hand side of the 28 | % constraints (size m x 1) 29 | % -- Eqin: presolved vector of the type of the constraints 30 | % (size m x 1) 31 | % -- c0: updated constant term of the objective function 32 | % -- infeasible: flag variable showing if the LP is 33 | % infeasible or not 34 | % -- unbounded: flag variable showing if the LP is unbounded 35 | % or not 36 | 37 | [m, n] = size(A); % find size of A 38 | % store the initial size of A to calculate the difference 39 | % after the presolve analysis 40 | minit = m; 41 | ninit = n; 42 | infeasible = 0; 43 | unbounded = 0; 44 | % if the constant term does not exist, set it to zero 45 | if(~exist('c0')) 46 | c0 = 0; 47 | end 48 | mprevious = 0; 49 | nprevious = 0; 50 | % call presolve methods until no change in matrix A 51 | while(mprevious ~= m || nprevious ~= n) 52 | % call presolve technique to eliminate zero rows 53 | [A, b, Eqin, infeasible] = eliminateZeroRows(A, b, Eqin); 54 | if(infeasible == 1) 55 | return; 56 | end 57 | % call presolve technique to eliminate zero columns 58 | [A, c, unbounded] = eliminateZeroColumns(A, c); 59 | if(unbounded == 1) 60 | return; 61 | end 62 | % call presolve technique to eliminate kton equality 63 | % constraints (as an example, we set kton = 2, i.e., 64 | % we eliminate doubleton and singleton constraints) 65 | [A, c, b, Eqin, c0, infeasible] = ... 66 | eliminateKtonEqualityConstraints(A, c, b, ... 67 | Eqin, c0, 2); 68 | if(infeasible == 1) 69 | return; 70 | end 71 | % call presolve technique to eliminate singleton 72 | % inequality constraints 73 | [A, c, b, Eqin, infeasible] = ... 74 | eliminateSingletonInequalityConstraints(A, c, ... 75 | b, Eqin); 76 | if(infeasible == 1) 77 | return; 78 | end 79 | % call presolve technique to eliminate dual singleton 80 | % equality constraints 81 | [A, c, b, Eqin, infeasible] = ... 82 | eliminateDualSingletonInequalityConstraints(A, ... 83 | c, b, Eqin); 84 | if(infeasible == 1) 85 | return; 86 | end 87 | % call presolve technique to eliminate implied free 88 | % singleton columns 89 | [A, c, b, Eqin, c0] = ... 90 | eliminateImpliedFreeSingletonColumns(A, c, b, ... 91 | Eqin, c0); 92 | % call presolve technique to eliminate redundant 93 | % columns 94 | [A, c] = eliminateRedundantColumns(A, c, b, Eqin); 95 | % call presolve technique to eliminate implied bounds 96 | % on rows 97 | [A, b, Eqin] = eliminateImpliedBoundsonRows(A, ... 98 | b, Eqin); 99 | % call presolve technique to eliminate zero columns 100 | [A, c, unbounded] = eliminateZeroColumns(A, c); 101 | if(unbounded == 1) 102 | return; 103 | end 104 | mprevious = m; 105 | nprevious = n; 106 | [m, n] = size(A); 107 | end 108 | % add slack variables 109 | Atemp = A; 110 | id = find(Eqin ~= 0); 111 | [m, ~] = size(A); 112 | for i = 1:length(id) 113 | if(Eqin(id(i)) == -1) % <= constraints 114 | ei = zeros(m, 1); 115 | ei(id(i)) = 1; 116 | Atemp = [Atemp ei]; 117 | else % >= constraints 118 | ei = zeros(m, 1); 119 | ei(id(i)) = -1; 120 | Atemp = [Atemp ei]; 121 | end 122 | end 123 | % call presolve technique to make the coefficient matrix 124 | % structurally full rank 125 | [A, b, Eqin] = fullRank(A, Atemp, b, Eqin); 126 | % call presolve technique to eliminate redundant rows 127 | [A, b, Eqin, infeasible] = eliminateRedundantRows(A,... 128 | b, Eqin); 129 | if(infeasible == 1) 130 | return; 131 | end 132 | % output statistics after the presolve analysis 133 | [m, n] = size(A); 134 | fprintf('========================================\n') 135 | fprintf(' (%i Constraints eliminated) \n', minit - m); 136 | fprintf(' (%i Variables eliminated) \n', ninit - n); 137 | fprintf(' ======================================== \n') 138 | fprintf(' ========FINAL REDUCTION (RESULTS)======= \n') 139 | fprintf(' ======================================== \n') 140 | fprintf(' %i Constraints \n', m); 141 | fprintf(' %i Variables \n', n); 142 | fprintf(' %i NonZeros \n', nnz(A)); 143 | fprintf(' ======================================== \n') 144 | end -------------------------------------------------------------------------------- /codes/chapter5/arithmeticMean.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = ... 2 | arithmeticMean(A, c, b) 3 | % Filename: arithmeticMean.m 4 | % Description: the function is an implementation of the 5 | % arithmetic mean scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multi, col_multi] = ... 9 | % arithmeticMean(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multi: vector of the row scaling factors 27 | % (size m x 1) 28 | % -- col_multi: vector of the column scaling factors 29 | % (size n x 1) 30 | 31 | [m, n] = size(A); % size of matrix A 32 | % first apply row scaling 33 | row_sum = zeros(m, 1); 34 | row_multi = zeros(m, 1); 35 | for i = 1:m 36 | % find the indices of the nonzero elements of the 37 | % specific row 38 | ind = find(A(i, :)); 39 | % if the specific row contains at least one nonzero 40 | % element 41 | if ~isempty(ind) 42 | % sum of the absolute value of the nonzero elements of 43 | % the specific row 44 | row_sum(i) = sum(sum(abs(A(i, ind)))); 45 | % calculate the specific row scaling factor 46 | row_multi(i) = length(ind) / row_sum(i); 47 | % scale the elements of the specific row of matrix A 48 | A(i, :) = A(i, :) * row_multi(i); 49 | % scale the elements of vector b 50 | b(i) = b(i) * row_multi(i); 51 | end 52 | end 53 | % then apply column scaling 54 | col_sum = zeros(n, 1); 55 | col_multi = zeros(n, 1); 56 | for j = 1:n 57 | % find the indices of the nonzero elements of the 58 | % specific column 59 | ind = find(A(:, j)); 60 | % if the specific column contains at least one nonzero 61 | % element 62 | if ~isempty(ind) 63 | % sum of the absolute value of the nonzero elements of 64 | % the specific column 65 | col_sum(j) = sum(sum(abs(A(ind, j)))); 66 | % calculate the specific column scaling factor 67 | col_multi(j) = length(ind) / col_sum(j); 68 | % scale the elements of the specific column of 69 | % matrix A 70 | A(:, j) = A(:, j) * col_multi(j); 71 | % scale the elements of vector c 72 | c(j) = c(j) * col_multi(j); 73 | end 74 | end 75 | end -------------------------------------------------------------------------------- /codes/chapter5/debuchet1.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = debuchet1(A, c, b) 2 | % Filename: debuchet1.m 3 | % Description: the function is an implementation of the de 4 | % Buchet for the case p = 1 scaling technique 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, row_multi, col_multi] = ... 8 | % debuchet1(A, c, b) 9 | % 10 | % Input: 11 | % -- A: matrix of coefficients of the constraints 12 | % (size m x n) 13 | % -- c: vector of coefficients of the objective function 14 | % (size n x 1) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % 18 | % Output: 19 | % -- A: scaled matrix of coefficients of the constraints 20 | % (size m x n) 21 | % -- c: scaled vector of coefficients of the objective 22 | % function (size n x 1) 23 | % -- b: scaled vector of the right-hand side of the 24 | % constraints (size m x 1) 25 | % -- row_multi: vector of the row scaling factors 26 | % (size m x 1) 27 | % -- col_multi: vector of the column scaling factors 28 | % (size n x 1) 29 | 30 | [m, n] = size(A); % size of matrix A 31 | % first apply row scaling 32 | row_sum = zeros(m, 1); 33 | row_inv_sum = zeros(m, 1); 34 | row_multi = zeros(m, 1); 35 | for i = 1:m 36 | % find the indices of the nonzero elements of the 37 | % specific row 38 | ind = find(A(i, :)); 39 | % if the specific row contains at least one nonzero 40 | % element 41 | if ~isempty(ind) 42 | % sum of the absolute value of the nonzero elements of 43 | % the specific row 44 | row_sum(i) = sum(sum(abs(A(i, ind)))); 45 | % sum of the inverse of the absolute value of the 46 | % nonzero elements of the specific row 47 | row_inv_sum(i) = sum(sum(abs(1 ./ A(i, ind)))); 48 | % calculate the specific row scaling factor 49 | row_multi(i) = (row_inv_sum(i) / row_sum(i))^(1 / 2); 50 | % scale the elements of the specific row of matrix A 51 | A(i, :) = A(i, :) * row_multi(i); 52 | % scale the elements of vector b 53 | b(i) = b(i) * row_multi(i); 54 | end 55 | end 56 | % then apply column scaling 57 | col_sum = zeros(n, 1); 58 | col_inv_sum = zeros(n, 1); 59 | col_multi = zeros(n, 1); 60 | for j = 1:n 61 | % find the indices of the nonzero elements of the 62 | % specific column 63 | ind = find(A(:, j)); 64 | % if the specific column contains at least one 65 | % nonzero element 66 | if ~isempty(ind) 67 | % sum of the absolute value of the nonzero elements of 68 | % the specific column 69 | col_sum(j) = sum(sum(abs(A(ind, j)))); 70 | % sum of the inverse of the absolute value of the 71 | % nonzero elements of the specific column 72 | col_inv_sum(j) = sum(sum(abs(1 ./ A(ind, j)))); 73 | % calculate the specific column scaling factor 74 | col_multi(j) = (col_inv_sum(j) / col_sum(j))^(1 / 2); 75 | % scale the elements of the specific column of 76 | % matrix A 77 | A(:, j) = A(:, j) * col_multi(j); 78 | % scale the elements of vector c 79 | c(j) = c(j) * col_multi(j); 80 | end 81 | end 82 | end -------------------------------------------------------------------------------- /codes/chapter5/debuchet2.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = debuchet2(A, c, b) 2 | % Filename: debuchet2.m 3 | % Description: the function is an implementation of the de 4 | % Buchet for the case p = 2 scaling technique 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, row_multi, col_multi] = ... 8 | % debuchet2(A, c, b) 9 | % 10 | % Input: 11 | % -- A: matrix of coefficients of the constraints 12 | % (size m x n) 13 | % -- c: vector of coefficients of the objective function 14 | % (size n x 1) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % 18 | % Output: 19 | % -- A: scaled matrix of coefficients of the constraints 20 | % (size m x n) 21 | % -- c: scaled vector of coefficients of the objective 22 | % function (size n x 1) 23 | % -- b: scaled vector of the right-hand side of the 24 | % constraints (size m x 1) 25 | % -- row_multi: vector of the row scaling factors 26 | % (size m x 1) 27 | % -- col_multi: vector of the column scaling factors 28 | % (size n x 1) 29 | 30 | [m, n] = size(A); % size of matrix A 31 | % first apply row scaling 32 | row_pow = zeros(m, 1); 33 | row_inv_pow = zeros(m, 1); 34 | row_multi = zeros(m, 1); 35 | for i = 1:m 36 | % find the indices of the nonzero elements of the 37 | % specific row 38 | ind = find(A(i, :)); 39 | % if the specific row contains at least one nonzero 40 | % element 41 | if ~isempty(ind) 42 | % sum of the value to the power of 2 of the nonzero 43 | % elements of the specific row 44 | row_pow(i) = sum(sum(A(i, ind) .* A(i, ind))); 45 | % sum of the inverse of the value to the power of 2 of 46 | % the nonzero elements of the specific row 47 | row_inv_pow(i) = sum(sum(1 ./ ... 48 | (abs(A(i, ind) .* A(i, ind))))); 49 | % calculate the specific row scaling factor 50 | row_multi(i) = (row_inv_pow(i) / row_pow(i))^(1 / 4); 51 | % scale the elements of the specific row of matrix A 52 | A(i, :) = A(i, :) * row_multi(i); 53 | % scale the elements of vector b 54 | b(i) = b(i) * row_multi(i); 55 | end 56 | end 57 | % then apply column scaling 58 | col_pow = zeros(n, 1); 59 | col_inv_pow = zeros(n, 1); 60 | col_multi = zeros(n, 1); 61 | for j = 1:n 62 | % find the indices of the nonzero elements of the 63 | % specific column 64 | ind = find(A(:,j)); 65 | % if the specific column contains at least one nonzero 66 | % element 67 | if ~isempty(ind) 68 | % sum of the value to the power of 2 of the nonzero 69 | % elements of the specific column 70 | col_pow(j) = sum(sum(A(ind, j) .* A(ind, j))); 71 | % sum of the inverse of the value to the power of 2 of 72 | % the nonzero elements of the specific column 73 | col_inv_pow(j) = sum(sum(1 ./ ... 74 | (abs(A(ind, j) .* A(ind, j))))); 75 | % calculate the specific column scaling factor 76 | col_multi(j) = (col_inv_pow(j) / col_pow(j))^(1 / 4); 77 | % scale the elements of the specific column of 78 | % matrix A 79 | A(:, j) = A(:, j) * col_multi(j); 80 | % scale the elements of vector c 81 | c(j) = c(j) * col_multi(j); 82 | end 83 | end 84 | end -------------------------------------------------------------------------------- /codes/chapter5/debuchetinf.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = ... 2 | debuchetinf(A, c, b) 3 | % Filename: debuchetinf.m 4 | % Description: the function is an implementation of the de 5 | % Buchet for the case p = inf scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multi, col_multi] = ... 9 | % debuchetinf(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multi: vector of the row scaling factors 27 | % (size m x 1) 28 | % -- col_multi: vector of the column scaling factors 29 | % (size n x 1) 30 | 31 | [m, n] = size(A); % size of matrix A 32 | % first apply row scaling 33 | row_max = zeros(m, 1); 34 | row_min = zeros(m, 1); 35 | row_multi = zeros(m, 1); 36 | for i = 1:m 37 | % find the indices of the nonzero elements of the 38 | % specific row 39 | ind = find(A(i, :)); 40 | % if the specific row contains at least one nonzero 41 | % element 42 | if ~isempty(ind) 43 | % find the maximum in absolute value of the nonzero 44 | % elements of the specific row 45 | row_max(i) = max(max(abs(A(i, ind)))); 46 | % find the minimum in absolute value of the nonzero 47 | % elements of the specific row 48 | row_min(i) = min(min(abs(A(i, ind)))); 49 | % calculate the specific row scaling factor 50 | row_multi(i) = 1 / (sqrt(row_max(i) * row_min(i))); 51 | % scale the elements of the specific row of matrix A 52 | A(i, :) = A(i, :) * row_multi(i); 53 | % scale the elements of vector b 54 | b(i) = b(i) * row_multi(i); 55 | end 56 | end 57 | % then apply column scaling 58 | col_max = zeros(n, 1); 59 | col_min = zeros(n, 1); 60 | col_multi = zeros(n, 1); 61 | for j = 1:n 62 | % find the indices of the nonzero elements of the 63 | % specific column 64 | ind = find(A(:, j)); 65 | % if the specific column contains at least one nonzero 66 | % element 67 | if ~isempty(ind) 68 | % find the maximum in absolute value of the nonzero 69 | % elements of the specific column 70 | col_max(j) = max(max(abs(A(ind, j)))); 71 | % find the minimum in absolute value of the nonzero 72 | % elements of the specific column 73 | col_min(j) = min(min(abs(A(ind, j)))); 74 | % calculate the specific column scaling factor 75 | col_multi(j) = 1 / (sqrt(col_max(j) * col_min(j))); 76 | % scale the elements of the specific column of 77 | % matrix A 78 | A(:, j) = A(:, j) * col_multi(j); 79 | % scale the elements of vector c 80 | c(j) = c(j) * col_multi(j); 81 | end 82 | end 83 | end -------------------------------------------------------------------------------- /codes/chapter5/entropy.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = entropy(A, c, b) 2 | % Filename: entropy.m 3 | % Description: the function is an implementation of the 4 | % entropy scaling technique 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, row_multi, col_multi] = entropy(A, c, b) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- c: vector of coefficients of the objective function 13 | % (size n x 1) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % 17 | % Output: 18 | % -- A: scaled matrix of coefficients of the constraints 19 | % (size m x n) 20 | % -- c: scaled vector of coefficients of the objective 21 | % function (size n x 1) 22 | % -- b: scaled vector of the right-hand side of the 23 | % constraints (size m x 1) 24 | % -- row_multi: vector of the row scaling factors 25 | % (size m x 1) 26 | % -- col_multi: vector of the column scaling factors 27 | % (size n x 1) 28 | 29 | [m, n] = size(A); % size of matrix A 30 | % first apply row scaling 31 | row_sum = zeros(m, 1); 32 | row_multi = zeros(m, 1); 33 | for i = 1:m 34 | % find the indices of the nonzero elements of the 35 | % specific row 36 | ind = find(A(i, :)); 37 | % if the specific row contains at least one nonzero 38 | % element 39 | if ~isempty(ind) 40 | % sum of the absolute value of the nonzero elements of 41 | % the specific row 42 | row_sum(i) = sum(sum(abs(A(i, ind)))); 43 | % calculate the specific row scaling factor 44 | row_multi(i) = length(ind) / row_sum(i); 45 | % scale the elements of the specific row of matrix A 46 | A(i, :) = A(i, :) * row_multi(i); 47 | % scale the elements of vector b 48 | b(i) = b(i) * row_multi(i); 49 | end 50 | end 51 | % then apply column scaling 52 | col_sum = zeros(n, 1); 53 | col_multi = zeros(n, 1); 54 | for j = 1:n 55 | % find the indices of the nonzero elements of the 56 | % specific column 57 | ind = find(A(:, j)); 58 | % if the specific column contains at least one nonzero 59 | % element 60 | if ~isempty(ind) 61 | % sum of the absolute value of the nonzero elements of 62 | % the specific column 63 | col_sum(j) = sum(sum(abs(A(ind, j)))); 64 | % calculate the specific column scaling factor 65 | col_multi(j) = length(ind) / col_sum(j); 66 | % scale the elements of the specific column of 67 | % matrix A 68 | A(:, j) = A(:, j) * col_multi(j); 69 | % scale the elements of vector c 70 | c(j) = c(j) * col_multi(j); 71 | end 72 | end 73 | end -------------------------------------------------------------------------------- /codes/chapter5/equilibration.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = ... 2 | equilibration(A, c, b) 3 | % Filename: equilibration.m 4 | % Description: the function is an implementation of the 5 | % equilibration scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multi, col_multi] = ... 9 | % equilibration(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multi: vector of the row scaling factors 27 | % (size m x 1) 28 | % -- col_multi: vector of the column scaling factors 29 | % (size n x 1) 30 | 31 | [m, n] = size(A); % size of matrix A 32 | % first apply row scaling 33 | row_max = zeros(m, 1); 34 | row_multi = zeros(m, 1); 35 | for i = 1:m 36 | % find the indices of the nonzero elements of the 37 | % specific row 38 | ind = find(A(i, :)); 39 | % if the specific row contains at least one nonzero 40 | % element 41 | if ~isempty(ind) 42 | % find the maximum in absolute value of the nonzero 43 | % elements of the specific row 44 | row_max(i) = max(max(abs(A(i, ind)))); 45 | % calculate the specific row scaling factor 46 | row_multi(i) = 1 / row_max(i); 47 | % scale the elements of the specific row of matrix A 48 | A(i, :) = A(i, :) * row_multi(i); 49 | % scale the elements of vector b 50 | b(i) = b(i) * row_multi(i); 51 | end 52 | end 53 | % then apply column scaling 54 | col_max = zeros(n, 1); 55 | col_multi = zeros(n, 1); 56 | for j = 1:n 57 | % find the indices of the nonzero elements of the 58 | % specific column 59 | ind = find(A(:, j)); 60 | % if the specific column contains at least one nonzero 61 | % element 62 | if ~isempty(ind) 63 | % find the maximum in absolute value of the nonzero 64 | % elements of the specific column 65 | col_max(j) = max(max(abs(A(ind, j)))); 66 | % calculate the specific column scaling factor 67 | col_multi(j) = 1 / col_max(j); 68 | % scale the elements of the specific column of 69 | % matrix A 70 | A(:, j) = A(:, j) * col_multi(j); 71 | % scale the elements of vector c 72 | c(j) = c(j) * col_multi(j); 73 | end 74 | end 75 | end -------------------------------------------------------------------------------- /codes/chapter5/geometricMean.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = ... 2 | geometricMean(A, c, b) 3 | % Filename: geometricMean.m 4 | % Description: the function is an implementation of the 5 | % geometric mean scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multi, col_multi] = ... 9 | % geometricMean(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multi: vector of the row scaling factors 27 | % (size m x 1) 28 | % -- col_multi: vector of the column scaling factors 29 | % (size n x 1) 30 | 31 | [m, n] = size(A); % size of matrix A 32 | % first apply row scaling 33 | row_max = zeros(m, 1); 34 | row_min = zeros(m, 1); 35 | row_multi = zeros(m, 1); 36 | for i = 1:m 37 | % find the indices of the nonzero elements of the 38 | % specific row 39 | ind = find(A(i, :)); 40 | % if the specific row contains at least one nonzero 41 | % element 42 | if ~isempty(ind) 43 | % find the maximum in absolute value of the nonzero 44 | % elements of the specific row 45 | row_max(i) = max(max(abs(A(i, ind)))); 46 | % find the minimum in absolute value of the nonzero 47 | % elements of the specific row 48 | row_min(i) = min(min(abs(A(i, ind)))); 49 | % calculate the specific row scaling factor 50 | row_multi(i) = 1 / (sqrt(row_max(i) * row_min(i))); 51 | % scale the elements of the specific row of matrix A 52 | A(i, :) = A(i, :) * row_multi(i); 53 | % scale the elements of vector b 54 | b(i) = b(i) * row_multi(i); 55 | end 56 | end 57 | % then apply column scaling 58 | col_max = zeros(n, 1); 59 | col_min = zeros(n, 1); 60 | col_multi = zeros(n, 1); 61 | for j = 1:n 62 | % find the indices of the nonzero elements of the 63 | % specific column 64 | ind = find(A(:, j)); 65 | % if the specific column contains at least one nonzero 66 | % element 67 | if ~isempty(ind) 68 | % find the maximum in absolute value of the nonzero 69 | % elements of the specific column 70 | col_max(j) = max(max(abs(A(ind, j)))); 71 | % find the minimum in absolute value of the nonzero 72 | % elements of the specific column 73 | col_min(j) = min(min(abs(A(ind, j)))); 74 | % calculate the specific column scaling factor 75 | col_multi(j) = 1 / (sqrt(col_max(j) * col_min(j))); 76 | % scale the elements of the specific column of 77 | % matrix A 78 | A(:, j) = A(:, j) * col_multi(j); 79 | % scale the elements of vector c 80 | c(j) = c(j) * col_multi(j); 81 | end 82 | end 83 | end -------------------------------------------------------------------------------- /codes/chapter5/ibmmpsx.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multigm, col_multigm, ... 2 | row_multieq, col_multieq] = ibmmpsx(A, c, b) 3 | % Filename: ibmmpsx.m 4 | % Description: the function is an implementation of the IBM 5 | % MPSX scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multigm, col_multigm, ... 9 | % row_multieq, col_multieq] = ibmmpsx(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multigm: vector of the row scaling factors from 27 | % geometric mean scaling technique (size m x 1) 28 | % -- col_multigm: vector of the column scaling factors from 29 | % geometric mean scaling technique (size n x 1) 30 | % -- row_multieq: vector of the row scaling factors from 31 | % equilibration scaling technique (size m x 1) 32 | % -- col_multieq: vector of the column scaling factors from 33 | % equilibration scaling technique (size n x 1) 34 | 35 | [m, n] = size(A); % size of matrix A 36 | row_multigm = zeros(m, 1); 37 | col_multigm = zeros(n, 1); 38 | row_multieq = zeros(m, 1); 39 | col_multieq = zeros(n, 1); 40 | max_A = max(max(A)); % find the maximum element of matrix A 41 | min_A = min(min(A)); % find the minimum element of matrix A 42 | tol = max(m, n) * eps * norm(A, 'inf'); 43 | tole = 10; % initialize tolerance 44 | % if the absolute value of the difference of the maximum 45 | % element and the minimum element are below tol, then do not 46 | % scale 47 | if abs(max_A - min_A) > tol 48 | counter = 0; 49 | % geometric mean is performed four times 50 | while(counter < 4) 51 | [A, c, b, row_multigm, col_multigm] = ... 52 | geometricMean(A, c, b); 53 | % or until the following relation holds true 54 | if((1 / nnz(A)) * (sum(sum(power(A, 2))) - ... 55 | power(sum(sum(abs(A))), 2) / nnz(A)) < tole) 56 | break; 57 | end 58 | counter = counter + 1; 59 | end 60 | % then equilibration scaling technique is performed 61 | [A, c, b, row_multieq, col_multieq] = ... 62 | equilibration(A, c, b); 63 | end 64 | end -------------------------------------------------------------------------------- /codes/chapter5/lpnorm1.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = lpnorm1(A, c, b) 2 | % Filename: lpnorm1.m 3 | % Description: the function is an implementation of the 4 | % Lp-norm for the case p = 1 scaling technique 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, row_multi, col_multi] = lpnorm1(A, c, b) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- c: vector of coefficients of the objective function 13 | % (size n x 1) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % 17 | % Output: 18 | % -- A: scaled matrix of coefficients of the constraints 19 | % (size m x n) 20 | % -- c: scaled vector of coefficients of the objective 21 | % function (size n x 1) 22 | % -- b: scaled vector of the right-hand side of the 23 | % constraints (size m x 1) 24 | % -- row_multi: vector of the row scaling factors 25 | % (size m x 1) 26 | % -- col_multi: vector of the column scaling factors 27 | % (size n x 1) 28 | 29 | [m, n] = size(A); % size of matrix A 30 | % first apply row scaling 31 | row_med = zeros(m, 1); 32 | row_multi = zeros(m, 1); 33 | for i = 1:m 34 | % find the indices of the nonzero elements of the 35 | % specific row 36 | ind = find(A(i, :)); 37 | % if the specific row contains at least one nonzero 38 | % element 39 | if ~isempty(ind) 40 | % find the median in absolute value of the nonzero 41 | % elements of the specific row 42 | row_med(i) = median(abs(A(i, ind))); 43 | % calculate the specific row scaling factor 44 | row_multi(i) = 1 / row_med(i); 45 | % scale the elements of the specific row of 46 | % matrix A 47 | A(i, :) = A(i, :) * row_multi(i); 48 | % scale the elements of vector b 49 | b(i) = b(i) * row_multi(i); 50 | end 51 | end 52 | % then apply column scaling 53 | col_med = zeros(n, 1); 54 | col_multi = zeros(n, 1); 55 | for j = 1:n 56 | % find the indices of the nonzero elements of the 57 | % specific column 58 | ind = find(A(:, j)); 59 | % if the specific column contains at least one 60 | % nonzero element 61 | if ~isempty(ind) 62 | % find the median in absolute value of the nonzero 63 | % elements of the specific column 64 | col_med(j) = median(abs(A(ind, j))); 65 | % calculate the specific column scaling factor 66 | col_multi(j) = 1 / col_med(j); 67 | % scale the elements of the specific column of 68 | % matrix A 69 | A(:, j) = A(:, j) * col_multi(j); 70 | % scale the elemens of vector c 71 | c(j) = c(j) * col_multi(j); 72 | end 73 | end 74 | end -------------------------------------------------------------------------------- /codes/chapter5/lpnorm2.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = lpnorm2(A, c, b) 2 | % Filename: lpnorm2.m 3 | % Description: the function is an implementation of the 4 | % Lp-norm for the case p = 2 scaling technique 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [A, c, b, row_multi, col_multi] = lpnorm2(A, c, b) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- c: vector of coefficients of the objective function 13 | % (size n x 1) 14 | % -- b: vector of the right-hand side of the constraints 15 | % (size m x 1) 16 | % 17 | % Output: 18 | % -- A: scaled matrix of coefficients of the constraints 19 | % (size m x n) 20 | % -- c: scaled vector of coefficients of the objective 21 | % function (size n x 1) 22 | % -- b: scaled vector of the right-hand side of the 23 | % constraints (size m x 1) 24 | % -- row_multi: vector of the row scaling factors 25 | % (size m x 1) 26 | % -- col_multi: vector of the column scaling factors 27 | % (size n x 1) 28 | 29 | [m, n] = size(A); % size of matrix A 30 | % first apply row scaling 31 | row_prod = zeros(m, 1); 32 | row_multi = zeros(m, 1); 33 | for i = 1:m 34 | % find the indices of the nonzero elements of the 35 | % specific row 36 | ind = find(A(i, :)); 37 | % if the specific row contains at least one nonzero 38 | % element 39 | if ~isempty(ind) 40 | % find the inverse of the product in absolute 41 | % value of the nonzero elements of the specific 42 | % row 43 | row_prod(i) = 1 / prod(abs(A(i, ind)))^ ... 44 | (-1 / length(ind)); 45 | % calculate the specific row scaling factor 46 | row_multi(i) = 1 / row_prod(i); 47 | % scale the elements of the specific row of matrix A 48 | A(i, :) = A(i, :) * row_multi(i); 49 | % scale the elements of vector b 50 | b(i) = b(i) * row_multi(i); 51 | end 52 | end 53 | % then apply column scaling 54 | col_prod = zeros(n, 1); 55 | col_multi = zeros(n, 1); 56 | for j = 1:n 57 | % find the indices of the nonzero elements of the 58 | % specific row 59 | ind = find(A(:, j)); 60 | % if the specific column contains at least one nonzero 61 | % element 62 | if ~isempty(ind) 63 | % find the inverse of the product in absolute value 64 | % of the nonzero elements of the specific column 65 | col_prod(j) = 1 / prod(abs(A(ind, j)))^ ... 66 | (-1 / length(ind)); 67 | % calculate the specific column scaling factor 68 | col_multi(j) = 1 / col_prod(j); 69 | % scale the elements of the specific column of 70 | % matrix A 71 | A(:, j) = A(:, j) * col_multi(j); 72 | % scale the elements of vector c 73 | c(j) = c(j) * col_multi(j); 74 | end 75 | end 76 | end -------------------------------------------------------------------------------- /codes/chapter5/lpnorminf.m: -------------------------------------------------------------------------------- 1 | function [A, c, b, row_multi, col_multi] = ... 2 | lpnorminf(A, c, b) 3 | % Filename: lpnorminf.m 4 | % Description: the function is an implementation of the 5 | % Lp-norm for the case p = inf scaling technique 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [A, c, b, row_multi, col_multi] = ... 9 | % lpnorminf(A, c, b) 10 | % 11 | % Input: 12 | % -- A: matrix of coefficients of the constraints 13 | % (size m x n) 14 | % -- c: vector of coefficients of the objective function 15 | % (size n x 1) 16 | % -- b: vector of the right-hand side of the constraints 17 | % (size m x 1) 18 | % 19 | % Output: 20 | % -- A: scaled matrix of coefficients of the constraints 21 | % (size m x n) 22 | % -- c: scaled vector of coefficients of the objective 23 | % function (size n x 1) 24 | % -- b: scaled vector of the right-hand side of the 25 | % constraints (size m x 1) 26 | % -- row_multi: vector of the row scaling factors 27 | % (size m x 1) 28 | % -- col_multi: vector of the column scaling factors 29 | % (size n x 1) 30 | 31 | [m, n] = size(A); % size of matrix A 32 | % first apply row scaling 33 | row_max = zeros(m, 1); 34 | row_min = zeros(m, 1); 35 | row_multi = zeros(m, 1); 36 | for i = 1:m 37 | % find the indices of the nonzero elements of the 38 | % specific row 39 | ind = find(A(i, :)); 40 | % if the specific row contains at least one nonzero 41 | % element 42 | if ~isempty(ind) 43 | % find the maximum in absolute value of the nonzero 44 | % elements of the specific row 45 | row_max(i) = max(max(abs(A(i, ind)))); 46 | % find the minimum in absolute value of the nonzero 47 | % elements of the specific row 48 | row_min(i) = min(min(abs(A(i, ind)))); 49 | % calculate the specific row scaling factor 50 | row_multi(i) = 1 / (sqrt(row_max(i) * row_min(i))); 51 | % scale the elements of the specific row of matrix A 52 | A(i, :) = A(i, :) * row_multi(i); 53 | % scale the elements of vector b 54 | b(i) = b(i) * row_multi(i); 55 | end 56 | end 57 | % then apply column scaling 58 | col_max = zeros(n, 1); 59 | col_min = zeros(n, 1); 60 | col_multi = zeros(n, 1); 61 | for j = 1:n 62 | % find the indices of the nonzero elements of the 63 | % specific column 64 | ind = find(A(:, j)); 65 | % if the specific column contains at least one nonzero 66 | % element 67 | if ~isempty(ind) 68 | % find the maximum in absolute value of the nonzero 69 | % elements of the specific column 70 | col_max(j) = max(max(abs(A(ind, j)))); 71 | % find the minimum in absolute value of the nonzero 72 | % elements of the specific column 73 | col_min(j) = min(min(abs(A(ind, j)))); 74 | % calculate the specific column scaling factor 75 | col_multi(j) = 1 / (sqrt(col_max(j) * col_min(j))); 76 | % scale the elements of the specific column of 77 | % matrix A 78 | A(:, j) = A(:, j) * col_multi(j); 79 | % scale the elements of vector c 80 | c(j) = c(j) * col_multi(j); 81 | end 82 | end 83 | end -------------------------------------------------------------------------------- /codes/chapter6/bland.m: -------------------------------------------------------------------------------- 1 | function [index] = bland(Sn, NonBasicList) 2 | % Filename: bland.m 3 | % Description: the function is an implementation of the 4 | % Bland's pivoting rule 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [index] = bland(Sn, NonBasicList) 8 | % 9 | % Input: 10 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 11 | % -- NonBasicList: vector of indices of the nonbasic 12 | % variables (size 1 x (n - m)) 13 | % 14 | % Output: 15 | % -- index: the index of the entering variable 16 | 17 | temp = find(Sn < 0); % find the indices of the eligible 18 | % variables that can enter the basis 19 | [~, b] = min(NonBasicList(temp)); % find the leftmost among 20 | % the eligible variables 21 | % calculate the index of the entering variable 22 | index = temp(b); 23 | end -------------------------------------------------------------------------------- /codes/chapter6/dantzig.m: -------------------------------------------------------------------------------- 1 | function [index] = dantzig(Sn) 2 | % Filename: dantzig.m 3 | % Description: the function is an implementation of the 4 | % Dantzig's pivoting rule 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [index] = dantzig(Sn) 8 | % 9 | % Input: 10 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 11 | % 12 | % Output: 13 | % -- index: the index of the entering variable 14 | 15 | [~, index] = min(Sn); % find the index of the variable 16 | % with the most negative Sn 17 | end -------------------------------------------------------------------------------- /codes/chapter6/gim.m: -------------------------------------------------------------------------------- 1 | function [index] = gim(Sn, NonBasicList, A, ... 2 | BasisInv, xb, tole) 3 | % Filename: gim.m 4 | % Description: the function is an implementation of the 5 | % Greatest Increment Method pivoting rule 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [index] = gim(Sn, NonBasicList, A, ... 9 | % BasisInv, xb, tole) 10 | % 11 | % Input: 12 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 13 | % -- NonBasicList: vector of indices of the nonbasic 14 | % variables (size 1 x (n - m)) 15 | % -- A: matrix of coefficients of the constraints 16 | % (size m x n) 17 | % -- BasisInv: matrix with the basis inverse (size m x m) 18 | % -- xb: vector with the values of the basic variables 19 | % (size m x 1) 20 | % -- tole: the value of the tolerance for the pivoting step 21 | % 22 | % Output: 23 | % -- index: the index of the entering variable 24 | 25 | index = -1; 26 | maxDecrease = 1; 27 | % calculate the improvement of the objective value for each 28 | % nonbasic variable 29 | for i = 1:length(NonBasicList) 30 | if Sn(i) >= 0 % only consider the eligible variables 31 | continue; 32 | end 33 | % store index of the candidate variable 34 | l = NonBasicList(i); 35 | hl = BasisInv * A(:, l); % compute the pivot column 36 | % set equal to zero the values of the pivot column that 37 | % are less than or equal to the given tolerance 38 | toler = abs(hl) <= tole; 39 | hl(toler == 1) = 0; 40 | mrt = find(hl > 0); 41 | % if there is not any variable in the pivot column 42 | % greater than zero, then the problem is unbounded 43 | if numel(mrt) < 1 44 | index = -1; 45 | return; 46 | end 47 | % calculate the total objective value improvement 48 | xbDIVhl = xb(mrt) ./ hl(mrt); 49 | theta0 = min(xbDIVhl(xbDIVhl > 0)); 50 | currDecrease = theta0 * Sn(i); 51 | % if this improvement is greater than the current 52 | % maximum improvement, store the value and the index 53 | if currDecrease < maxDecrease 54 | maxDecrease = currDecrease; 55 | index = i; 56 | end 57 | end 58 | % if the entering variable is empty, then find the index 59 | % of the variable with the most negative Sn 60 | if index < 0 61 | [~, index] = min(Sn); 62 | end 63 | end -------------------------------------------------------------------------------- /codes/chapter6/lrcm.m: -------------------------------------------------------------------------------- 1 | function [index] = lrcm(Sn, NonBasicList, lrcmLast, ... 2 | iteration) 3 | % Filename: lrcm.m 4 | % Description: the function is an implementation of the 5 | % Least Recently Considered Method pivoting rule 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [index] = lrcm(Sn, NonBasicList, lrcmLast, ... 9 | % iteration) 10 | % 11 | % Input: 12 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 13 | % -- NonBasicList: vector of indices of the nonbasic 14 | % variables (size 1 x (n - m)) 15 | % -- lrcmLast: the index of the last selected entering 16 | % variable 17 | % -- iteration: the current iteration of the simplex 18 | % algorithm 19 | % 20 | % Output: 21 | % -- index: the index of the entering variable 22 | 23 | % use Dantzig's rule in the first iteration 24 | if iteration == 1 25 | [~, index] = min(Sn); 26 | else 27 | % searching for the first eligible variable with index 28 | % greater than lrcmLast 29 | temp1 = find(Sn < 0); 30 | temp2 = NonBasicList(temp1); 31 | temp3 = find(temp2 > lrcmLast); 32 | % if not any eligible variable with index greater than 33 | % lrcmLast, start searching from the first column again 34 | if isempty(temp3) 35 | [~, b] = min(temp2); 36 | index = temp1(b); 37 | else 38 | index = temp1(min(temp3)); 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /codes/chapter6/partialPricing.m: -------------------------------------------------------------------------------- 1 | function [index] = partialPricing(Sn, segmentSize) 2 | % Filename: partialPricing.m 3 | % Description: the function is an implementation of the 4 | % static partial pricing method using Dantzig's pivoting 5 | % rule 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [index] = partialPricing(Sn) 9 | % 10 | % Input: 11 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 12 | % -- segmentSize: the size of the segment 13 | % 14 | % Output: 15 | % -- index: the index of the entering variable 16 | 17 | currentSegment = 1; % initialize current segment 18 | negativeFound = 0; 19 | partialSn = []; 20 | % stop when a negative value is found in Sn 21 | while negativeFound == 0 22 | % the start of the segment 23 | Nstart = (currentSegment - 1) * segmentSize + 1; 24 | % the end of the segment 25 | Nend = Nstart + segmentSize - 1; 26 | % if the end is greater than the length of Sn, set 27 | % Nend = length(Sn) 28 | if Nend > length(Sn) 29 | Nend = length(Sn); 30 | end 31 | % check if a negative value exists in that segment 32 | % or otherwise continue with the next segment 33 | partialSn = Sn(Nstart:Nend); 34 | negativeFound = ~isempty(find(partialSn < 0)); 35 | if negativeFound == 1 36 | % find the index of the variable with the most 37 | % negative Sn 38 | [~, index] = min(partialSn); 39 | % find the position in the original vector Sn 40 | index = index + Nstart - 1; 41 | else % next segment 42 | currentSegment = currentSegment + 1; 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /codes/chapter6/partialPricingInitial.m: -------------------------------------------------------------------------------- 1 | function [index] = partialPricingInitial(Sn) 2 | % Filename: partialPricing.m 3 | % Description: the function is an implementation of the 4 | % static partial pricing method using Dantzig's pivoting 5 | % rule 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [index] = partialPricing(Sn) 9 | % 10 | % Input: 11 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 12 | % 13 | % Output: 14 | % -- index: the index of the entering variable 15 | 16 | % find the index of the variable with the most 17 | % negative Sn 18 | [~, index] = min(Sn); 19 | end -------------------------------------------------------------------------------- /codes/chapter6/partialPricingUpdate.m: -------------------------------------------------------------------------------- 1 | function [Sn] = partialPricingUpdate(A, c, BasicList, ... 2 | NonBasicList, BasisInv, tole, segmentSize) 3 | % Filename: partialPricingUpdate.m 4 | % Description: the function is an implementation of the 5 | % update routine for the static partial pricing method 6 | % using Dantzig's pivoting rule 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [index] = partialpricingupdate(Sn, A, BasicList, ... 10 | % NonBasicList, BasisInv, tole, segmentSize) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- c: vector of coefficients of the objective function 16 | % (size n x 1) 17 | % -- BasicList: vector of indices of the basic variables 18 | % (size 1 x m) 19 | % -- NonBasicList: vector of indices of the nonbasic 20 | % variables (size 1 x (n - m)) 21 | % -- BasisInv: matrix with the basis inverse (size m x m) 22 | % -- tole: the value of the tolerance for the pivoting step 23 | % -- segmentSize: the size of the segment 24 | 25 | % Output: 26 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 27 | % 28 | % initialize vectors cb, cn, w and Sn 29 | cb = c(BasicList); 30 | cn = c(NonBasicList); 31 | w = cb * BasisInv; 32 | Sn = zeros(size(cn), 1); 33 | currentSegment = 1; % initialize current segment 34 | negativeFound = false; 35 | Nend = 0; 36 | % stop when a negative value is found in Sn or when we 37 | % finished searching all segments 38 | while negativeFound == false && Nend < length(cn) 39 | % the start of the segment 40 | Nstart = (currentSegment - 1) * segmentSize + 1; 41 | % the end of the segment 42 | Nend = Nstart + segmentSize - 1; 43 | % if the end is greater than the length of Sn, set 44 | % Nend = length(Sn) 45 | if Nend > length(cn) 46 | Nend = length(cn); 47 | end 48 | % calculate Sn 49 | N = A(:, NonBasicList); 50 | HRN = w * N(:, Nstart:Nend); 51 | Sn(Nstart:Nend) = cn(Nstart:Nend) - HRN; 52 | % set to zero, the values of Sn that are less than or 53 | % equal to tole 54 | toler = abs(Sn) <= tole; 55 | Sn(toler == 1) = 0; 56 | % check if a negative value exists in Sn or otherwise 57 | % continue with the next segment 58 | negativeFound = ~isempty(Sn < 0); 59 | currentSegment = currentSegment + 1; 60 | end 61 | end -------------------------------------------------------------------------------- /codes/chapter6/steepestEdge.m: -------------------------------------------------------------------------------- 1 | function [index] = steepestEdge(Sn, NonBasicList, ... 2 | A, BasisInv) 3 | % Filename: steepestEdge.m 4 | % Description: the function is an implementation of the 5 | % Steepest Edge pivoting rule 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [index] = steepestEdge(Sn, NonBasicList, ... 9 | % A, BasisInv) 10 | % 11 | % Input: 12 | % -- Sn: vector of reduced costs (size 1 x (n - m)) 13 | % -- NonBasicList: vector of indices of the nonbasic 14 | % variables (size 1 x (n - m)) 15 | % -- A: matrix of coefficients of the constraints 16 | % (size m x n) 17 | % -- BasisInv: matrix with the basis inverse (size m x m) 18 | % 19 | % Output: 20 | % -- index: the index of the entering variable 21 | 22 | % calculate the denominator of the equation 23 | Y = BasisInv * A(:, NonBasicList); 24 | nd = sqrt(1 + diag(Y' * Y)); 25 | % calculate the index of the minimum value of the division 26 | % of the vector Sn to vector nd 27 | [~, j] = min(Sn'./ nd); 28 | index = j(1); 29 | end -------------------------------------------------------------------------------- /codes/chapter7/gaussjordanElimination.m: -------------------------------------------------------------------------------- 1 | function [BasisInv] = gaussjordanElimination(A, BasicList) 2 | % Filename: gaussjordanElimination.m 3 | % Description: the function is an implementation of the 4 | % Gauss-Jordan elimination basis inverse method 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [BasisInv] = gaussjordanElimination(A, BasicList) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- BasicList: vector of indices of the basic variables 13 | % (size 1 x m) 14 | % 15 | % Output: 16 | % -- BasisInv: matrix with the new basis inverse (size m x m) 17 | 18 | BasisInv = A(:, BasicList) \ speye(length(BasicList)); 19 | end -------------------------------------------------------------------------------- /codes/chapter7/luInverse.m: -------------------------------------------------------------------------------- 1 | function [BasisInv] = luInverse(A, BasicList) 2 | % Filename: luInverse.m 3 | % Description: the function is an implementation of the LU 4 | % Decomposition method to find the inverse of a matrix 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [BasisInv] = luInverse(A, BasicList) 8 | % 9 | % Input: 10 | % -- A: matrix of coefficients of the constraints 11 | % (size m x n) 12 | % -- BasicList: vector of indices of the basic variables 13 | % (size 1 x m) 14 | % 15 | % Output: 16 | % -- BasisInv: matrix with the new basis inverse (size m x m) 17 | 18 | % compute L and U matrices 19 | [L, U] = lu(A(:, BasicList)); 20 | % calculate the basis inverse 21 | BasisInv = U \ (L \ (speye(length(BasicList)))); 22 | end -------------------------------------------------------------------------------- /codes/chapter7/mpfi.m: -------------------------------------------------------------------------------- 1 | function [BasisInv] = mpfi(BasisInv, h_l, r) 2 | % Filename: mpfi.m 3 | % Description: the function is an implementation of the 4 | % Modification of the Product Form of the Inverse basis 5 | % update method 6 | % Authors: Ploskas, N., & Samaras, N. 7 | % 8 | % Syntax: [BasisInv] = mpfi(BasisInv, h_l, r) 9 | % 10 | % Input: 11 | % -- BasisInv: matrix with the basis inverse (size m x m) 12 | % -- h_l: vector with pivot column (size m x 1) 13 | % -- r: the index of the leaving variable 14 | % 15 | % Output: 16 | % -- BasisInv: matrix with the new basis inverse (size m x m) 17 | 18 | eta = -h_l / h_l(r); % compute the eta column vector 19 | eta(r) = 1 / h_l(r); 20 | K = eta * BasisInv(r, :); % perform a simple outer product 21 | BasisInv(r, :) = 0; % set equal to zero the elements in the 22 | % row r of the basis inverse 23 | BasisInv = BasisInv + K; % add the matrices 24 | end -------------------------------------------------------------------------------- /codes/chapter7/pfi.m: -------------------------------------------------------------------------------- 1 | function [BasisInv] = pfi(BasisInv, h_l, r) 2 | % Filename: pfi.m 3 | % Description: the function is an implementation of the 4 | % Product Form of the Inverse basis update method 5 | % Authors: Ploskas, N., & Samaras, N. 6 | % 7 | % Syntax: [BasisInv] = pfi(BasisInv, h_l, r) 8 | % 9 | % Input: 10 | % -- BasisInv: matrix with the basis inverse (size m x m) 11 | % -- h_l: vector with pivot column (size m x 1) 12 | % -- r: the index of the leaving variable 13 | % 14 | % Output: 15 | % -- BasisInv: matrix with the new basis inverse 16 | % (size m x m) 17 | 18 | eta = -h_l / h_l(r); % compute the eta column vector 19 | eta(r) = 1 / h_l(r); 20 | EInv = speye(length(BasisInv)); % create eta matrix 21 | EInv(:, r) = eta; 22 | BasisInv = EInv * BasisInv; % calculate new basis inverse 23 | end -------------------------------------------------------------------------------- /codes/chapter8/lprref.m: -------------------------------------------------------------------------------- 1 | function [AEqin, bEqin, jb, out, rowindex, ... 2 | infeasible] = lprref(A, b, Eqin, tol) 3 | % Filename: lprref.m 4 | % Description: the function calculates a row echelon 5 | % form of matrix A for LPs using Gauss-Jordan 6 | % elimination with partial pivoting 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [AEqin, bEqin, jb, out, rowindex, ... 10 | % infeasible] = lprref(A, b, Eqin, tol) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % -- Eqin: vector of the type of the constraints 18 | % (size m x 1) 19 | % -- tol: tolerance 20 | % 21 | % Output: 22 | % -- AEqin: reduced row echelon form of A (size m x n) 23 | % -- bEqin: reduced vector b (size m x 1) 24 | % -- jb: basis of matrix A (size m x m) 25 | % -- rowindex: a matrix with the row redundant indices 26 | % (size 2 x m) 27 | % -- infeasible: if the problem is infeasible or not 28 | 29 | % initialize output variables 30 | infeasible = 0; 31 | out = []; 32 | % find all equality constraints 33 | a0 = find(Eqin == 0); 34 | AEqin = A(a0, :); 35 | bEqin = b(a0, :); 36 | [m, n] = size(AEqin); 37 | rowindex = zeros(2, m); 38 | rowindex(1, 1:m) = a0'; 39 | if nargin < 4 % compute tol, if it was not given as input 40 | tol = max(m, n) * eps * norm(A, 'inf'); 41 | end 42 | i = 1; 43 | j = 1; 44 | jb = []; 45 | % apply Gauss-Jordan elimination with partial pivoting 46 | while (i <= m) && (j <= n) 47 | [p, k] = max(abs(AEqin(i:m, j))); 48 | if p < tol 49 | AEqin(i:m, j) = zeros(m - i + 1, 1); 50 | j = j + 1; 51 | elseif p ~= 0 52 | k = k + i - 1; 53 | jb = [jb j]; 54 | AEqin([i k], :) = AEqin([k i], :); 55 | bEqin([i k], :) = bEqin([k i], :); 56 | rowindex(:, [i k]) = rowindex(:, [k i]); 57 | bEqin(i, :) = bEqin(i, :) / AEqin(i, j); 58 | AEqin(i, j:n) = AEqin(i, j:n) / AEqin(i, j); 59 | i_nz = find(AEqin(:, j)); 60 | i_nz = setdiff(i_nz, i); 61 | for t = i_nz 62 | if bEqin(i) ~= 0 63 | bEqin(t) = bEqin(t) - AEqin(t, j) * bEqin(i); 64 | toler = abs(bEqin) <= tol; 65 | bEqin(toler == 1) = 0; 66 | end 67 | AEqin(t, j:n) = AEqin(t, j:n) - ... 68 | AEqin(t, j) * AEqin(i, j:n); 69 | toler = abs(AEqin) <= tol; 70 | AEqin(toler == 1) = 0; 71 | end 72 | i = i + 1; 73 | j = j + 1; 74 | end 75 | end 76 | % check for redundant and infeasible constraints 77 | i = 1; 78 | for h = [1:i - 1 i + 1:m] 79 | % redundant constraint 80 | if (AEqin(h, :) == 0) & (bEqin(h) == 0) 81 | rowindex(2, h) = 1; 82 | end 83 | % infeasible constraint 84 | if (AEqin(h,:) == 0) & (bEqin(h) ~= 0) 85 | infeasible = 1; 86 | return; 87 | end 88 | end 89 | % find the indices of the redundant constraints 90 | if any(rowindex(2, :) == 1) 91 | y = find(rowindex(2, :) == 1); 92 | out = y; 93 | end 94 | end -------------------------------------------------------------------------------- /codes/chapter9/lprref.m: -------------------------------------------------------------------------------- 1 | function [AEqin, bEqin, jb, out, rowindex, ... 2 | infeasible] = lprref(A, b, Eqin, tol) 3 | % Filename: lprref.m 4 | % Description: the function calculates a row echelon 5 | % form of matrix A for LPs using Gauss-Jordan 6 | % elimination with partial pivoting 7 | % Authors: Ploskas, N., & Samaras, N. 8 | % 9 | % Syntax: [AEqin, bEqin, jb, out, rowindex, ... 10 | % infeasible] = lprref(A, b, Eqin, tol) 11 | % 12 | % Input: 13 | % -- A: matrix of coefficients of the constraints 14 | % (size m x n) 15 | % -- b: vector of the right-hand side of the constraints 16 | % (size m x 1) 17 | % -- Eqin: vector of the type of the constraints 18 | % (size m x 1) 19 | % -- tol: tolerance 20 | % 21 | % Output: 22 | % -- AEqin: reduced row echelon form of A (size m x n) 23 | % -- bEqin: reduced vector b (size m x 1) 24 | % -- jb: basis of matrix A (size m x m) 25 | % -- rowindex: a matrix with the row redundant indices 26 | % (size 2 x m) 27 | % -- infeasible: if the problem is infeasible or not 28 | 29 | % initialize output variables 30 | infeasible = 0; 31 | out = []; 32 | % find all equality constraints 33 | a0 = find(Eqin == 0); 34 | AEqin = A(a0, :); 35 | bEqin = b(a0, :); 36 | [m, n] = size(AEqin); 37 | rowindex = zeros(2, m); 38 | rowindex(1, 1:m) = a0'; 39 | if nargin < 4 % compute tol, if it was not given as input 40 | tol = max(m, n) * eps * norm(A, 'inf'); 41 | end 42 | i = 1; 43 | j = 1; 44 | jb = []; 45 | % apply Gauss-Jordan elimination with partial pivoting 46 | while (i <= m) && (j <= n) 47 | [p, k] = max(abs(AEqin(i:m, j))); 48 | if p < tol 49 | AEqin(i:m, j) = zeros(m - i + 1, 1); 50 | j = j + 1; 51 | elseif p ~= 0 52 | k = k + i - 1; 53 | jb = [jb j]; 54 | AEqin([i k], :) = AEqin([k i], :); 55 | bEqin([i k], :) = bEqin([k i], :); 56 | rowindex(:, [i k]) = rowindex(:, [k i]); 57 | bEqin(i, :) = bEqin(i, :) / AEqin(i, j); 58 | AEqin(i, j:n) = AEqin(i, j:n) / AEqin(i, j); 59 | i_nz = find(AEqin(:, j)); 60 | i_nz = setdiff(i_nz, i); 61 | for t = i_nz 62 | if bEqin(i) ~= 0 63 | bEqin(t) = bEqin(t) - AEqin(t, j) * bEqin(i); 64 | toler = abs(bEqin) <= tol; 65 | bEqin(toler == 1) = 0; 66 | end 67 | AEqin(t, j:n) = AEqin(t, j:n) - ... 68 | AEqin(t, j) * AEqin(i, j:n); 69 | toler = abs(AEqin) <= tol; 70 | AEqin(toler == 1) = 0; 71 | end 72 | i = i + 1; 73 | j = j + 1; 74 | end 75 | end 76 | % check for redundant and infeasible constraints 77 | i = 1; 78 | for h = [1:i - 1 i + 1:m] 79 | % redundant constraint 80 | if (AEqin(h, :) == 0) & (bEqin(h) == 0) 81 | rowindex(2, h) = 1; 82 | end 83 | % infeasible constraint 84 | if (AEqin(h,:) == 0) & (bEqin(h) ~= 0) 85 | infeasible = 1; 86 | return; 87 | end 88 | end 89 | % find the indices of the redundant constraints 90 | if any(rowindex(2, :) == 1) 91 | y = find(rowindex(2, :) == 1); 92 | out = y; 93 | end 94 | end -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Springer Source Code 2 | 3 | Copyright for Springer source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! -------------------------------------------------------------------------------- /cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/springer-math/linear-programming-using-MATLAB/984d0366b7cc8e6df67424d7bcd7505fb72bf782/cover.jpg -------------------------------------------------------------------------------- /errata.md: -------------------------------------------------------------------------------- 1 | # Errata for *Linear Programming Using MATLAB®* 2 | 3 | 1. p. 24, function general2standard: the correct version of the file general2standard.m can be found on https://github.com/springer-math/linear-programming-using-MATLAB/blob/master/codes/chapter2/general2standard.m 4 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) 2018, Stephen Lynch 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the distribution 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------