alpar@1: /* min01ks.mod - finding minimal equivalent 0-1 knapsack inequality */ alpar@1: alpar@1: /* Written in GNU MathProg by Andrew Makhorin */ alpar@1: alpar@1: /* It is obvious that for a given 0-1 knapsack inequality alpar@1: alpar@1: a[1] x[1] + ... + a[n] x[n] <= b, x[j] in {0, 1} (1) alpar@1: alpar@1: there exist infinitely many equivalent inequalities with exactly the alpar@1: same feasible solutions. alpar@1: alpar@1: Given a[j]'s and b this model allows to find an inequality alpar@1: alpar@1: alfa[1] x[1] + ... + alfa[n] x[n] <= beta, x[j] in {0, 1}, (2) alpar@1: alpar@1: which is equivalent to (1) and where alfa[j]'s and beta are smallest alpar@1: non-negative integers. alpar@1: alpar@1: This model has the following formulation: alpar@1: alpar@1: minimize alpar@1: alpar@1: z = |alfa[1]| + ... + |alfa[n]| + |beta| = (3) alpar@1: alpar@1: = alfa[1] + ... + alfa[n] + beta alpar@1: alpar@1: subject to alpar@1: alpar@1: alfa[1] x[1] + ... + alfa[n] x[n] <= beta (4) alpar@1: alpar@1: for all x satisfying to (1) alpar@1: alpar@1: alfa[1] x[1] + ... + alfa[n] x[n] >= beta + 1 (5) alpar@1: alpar@1: for all x not satisfying to (1) alpar@1: alpar@1: alfa[1], ..., alfa[n], beta are non-negative integers. alpar@1: alpar@1: Note that this model has n+1 variables and 2^n constraints. alpar@1: alpar@1: It is interesting, as noticed in [1] and explained in [2], that alpar@1: in most cases LP relaxation of the MIP formulation above has integer alpar@1: optimal solution. alpar@1: alpar@1: References alpar@1: alpar@1: 1. G.H.Bradley, P.L.Hammer, L.Wolsey, "Coefficient Reduction for alpar@1: Inequalities in 0-1 Variables", Math.Prog.7 (1974), 263-282. alpar@1: alpar@1: 2. G.J.Koehler, "A Study on Coefficient Reduction of Binary Knapsack alpar@1: Inequalities", University of Florida, 2001. */ alpar@1: alpar@1: param n, integer, > 0; alpar@1: /* number of variables in the knapsack inequality */ alpar@1: alpar@1: set N := 1..n; alpar@1: /* set of knapsack items */ alpar@1: alpar@1: /* all binary n-vectors are numbered by 0, 1, ..., 2^n-1, where vector alpar@1: 0 is 00...00, vector 1 is 00...01, etc. */ alpar@1: alpar@1: set U := 0..2^n-1; alpar@1: /* set of numbers of all binary n-vectors */ alpar@1: alpar@1: param x{i in U, j in N}, binary, := (i div 2^(j-1)) mod 2; alpar@1: /* x[i,j] is j-th component of i-th binary n-vector */ alpar@1: alpar@1: param a{j in N}, >= 0; alpar@1: /* original coefficients */ alpar@1: alpar@1: param b, >= 0; alpar@1: /* original right-hand side */ alpar@1: alpar@1: set D := setof{i in U: sum{j in N} a[j] * x[i,j] <= b} i; alpar@1: /* set of numbers of binary n-vectors, which (vectors) are feasible, alpar@1: i.e. satisfy to the original knapsack inequality (1) */ alpar@1: alpar@1: var alfa{j in N}, integer, >= 0; alpar@1: /* coefficients to be found */ alpar@1: alpar@1: var beta, integer, >= 0; alpar@1: /* right-hand side to be found */ alpar@1: alpar@1: minimize z: sum{j in N} alfa[j] + beta; /* (3) */ alpar@1: alpar@1: phi{i in D}: sum{j in N} alfa[j] * x[i,j] <= beta; /* (4) */ alpar@1: alpar@1: psi{i in U diff D}: sum{j in N} alfa[j] * x[i,j] >= beta + 1; /* (5) */ alpar@1: alpar@1: solve; alpar@1: alpar@1: printf "\nOriginal 0-1 knapsack inequality:\n"; alpar@1: for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", alpar@1: a[j], j; alpar@1: printf " <= %g\n", b; alpar@1: printf "\nMinimized equivalent inequality:\n"; alpar@1: for {j in 1..n} printf (if j = 1 then "" else " + ") & "%g x%d", alpar@1: alfa[j], j; alpar@1: printf " <= %g\n\n", beta; alpar@1: alpar@1: data; alpar@1: alpar@1: /* These data correspond to the very first example from [1]. */ alpar@1: alpar@1: param n := 8; alpar@1: alpar@1: param a := [1]65, [2]64, [3]41, [4]22, [5]13, [6]12, [7]8, [8]2; alpar@1: alpar@1: param b := 80; alpar@1: alpar@1: end;