Integer Knapsack as a Backtracking Problem -- With Bounding Function

Document Sample
Integer Knapsack as a Backtracking Problem -- With Bounding Function Powered By Docstoc
					                            Integer Knapsack as a Backtracking Problem — WITH Bounding Function
/**                                                                     /**
 * Integer knapsack problem: Based on item weights and values,           * Integer knapsack through backtracking --- implementation
 * find the combination of _multiples_ items to include in the           * to retain information about the knapsack contents.
 * knapsack that will maximize the value, subject to a weight            *
 * limitation.                                                           * Parameters:
 *                                                                       *    maxWt     --- carrying capacity of the knapsack
 * This uses adds a value bound to the backtracking --- the              *    used[]    --- current knapsack contents
 * input data is sorted into decreasing val/wt ratios. Then              *    item      --- position being considered.
 * the bounding function is to check whether completely filling          *    weight[] --- individual weights
 * the sack with the current item _allowing_fractional_part_             *    value[]   --- individual values
 * would generate a load better than the current maximum. If             *    pack[]    --- retain the OPTIMAL boolean vector
 * not, backtrack immediately.                                           *    current[] --- [0] current weight, [1] current value,
 *                                                                       *                  and [2] current MAXIMUM value
 * For a dataset which, in the unbounded backtracking implementation,    *
 * uses 89 invocations of the recursive method, this implementation      * Decision tree pruning: proceed if COMPLETELY filling
 * uses 31 invocations.                                                  * the knapsack with the current item (including fractional
 *                                                                       * part) is better than the current maximum.
 * Author: Timothy Rolfe                                                 *
 */                                                                      * This presumes that the weight and value vectors have
import java.io.*;                                                        * been sorted to present items from greatest to smallest
import java.util.*;     // Scanner etc.                                  * value per weight ratio.
                                                                         */
public class IntKS_Bound
                                                                           static void knapSack(int maxWt, int[] used, int item,
{//If DEBUG is turned on, show each new solution as discovered
                                                                                                int [] weight, int [] value,
   final static boolean DEBUG = true;
                                                                                                int [] pack, int[] current)
   static int nCalls;
                                                                           { double usable;     // How MUCH of this item could we get in?
/**
                                                                              nCalls++;         // Tally number of method invocations
 * Public method will call the recursive branch-and-bound method
                                                                           // Check whether all positions have been considered
 *
                                                                              if (item == pack.length)
 * The value bound demands that the weight and value vectors
                                                                              {//Do we have a winner?
 * be sorted into non-increasing value-per-weight ratios.
                                                                                 if ( current[1] > current[2] )
 *
                                                                                 { if (DEBUG)
 * The recursive method needs to receive and update information
                                                                                    { System.out.println (current[1] + " replaces " +
 * on the current state and the optimal solution. This is
                                                                                                           current[2]);
 * handled through passing arrays.
                                                                                       display(weight, value, used);
 *
                                                                                       System.out.println();
 * current[] will hold [0] current weight, [1] current value,
                                                                                    }
 * and [2] current MAXIMUM value;
                                                                                 // Save the state for this winner
 *
                                                                                    current[2] = current[1];
 * pack[] will be the int vector corresponding to that
                                                                                    System.arraycopy(used, 0, pack, 0, used.length);
 * current MAXIMUM value. It contains the number of each
                                                                                 }
 * item included in the winning load.
                                                                              }
 *
                                                                              else
 * used[] is the scratch int vector used to generate the
                                                                              {//Compute how many of this item we would use if we just loaded
 * possible knapsacks.
                                                                               // up with it, then try from that value backwards to zero. Note
 */
                                                                               // that bounding requires us to allow a fractional part.
   public static void knapSack(int maxWt, int [] pack,
                                                                                 usable = (double) (maxWt - current[0]) / weight[item];
                               int [] weight, int [] value)
   { int[] current = { 0, 0, Integer.MIN_VALUE };                             // Bound based on increase in value from using JUST THIS, including
      int[] used = new int[pack.length];                                      // a fractional part.
                                                                                 if ( usable >= 1 && usable*value[item]+current[1] > current[2] )
       sort (weight, value);
                                                                                 { used[item] = (int) usable;
       knapSack(maxWt, used, 0, weight, value, pack, current);
                                                                                    current[0] += used[item] * weight[item];
   }
                                                                                    current[1] += used[item] * value[item];


Printed on 2010-09-03 at 14:46
              while ( used[item] > 0 )                                              System.out.println ("Total method invocations:   " + nCalls);
              { knapSack(maxWt, used, item+1, weight, value,                    }
                          pack, current);
                                                                                static void swap ( int p, int q, int[] x)
              // Back off on the number of this type item
                                                                                { int tmp = x[p]; x[p] = x[q]; x[q] = tmp;     }
                 used[item]--;
                 current[0] -= weight[item];                                    static void sort ( int[] wt, int[] val )
                 current[1] -= value[item];                                     { for ( int lim = wt.length-1; lim > 0; lim-- )
              }                                                                    { int min = 0;
          }
                                                                                        for ( int k = 1; k <= lim; k++ )
//**/     else if ( DEBUG && usable >= 1.0 )
                                                                                           if ( (double)val[k]/wt[k] < (double)val[min]/wt[min] )
//**/        System.out.println ("Bound function discards item " + item);
                                                                                              min = k;
        // Whether we used one or not, go forward WITHOUT using any.                    swap ( min, lim, wt );
           knapSack(maxWt, used, item+1, weight, value,                                 swap ( min, lim, val );
                    pack, current);                                                 }
        }                                                                       }
   }
                                                                                static Scanner console = new Scanner(System.in);
   static void display(int [] weight, int [] value, int [] pack)                static Scanner openInput ( String lineIn )
   { int k, sumWeight=0, sumValue=0;                                            { Scanner inp = null;
                                                                                    if ( lineIn == null || lineIn.length() == 0 )
        for ( k = 0; k < pack.length; k++ )
                                                                                    {
           if ( pack[k] > 0 )
                                                                                       System.out.print ("input file: ");
           { sumWeight += weight[k] * pack[k];
                                                                                       lineIn = console.nextLine();
              sumValue += value[k] * pack[k];
                                                                                    }
              System.out.println ("(" + pack[k] + " used: " +
                                  weight[k] + ", " + value[k] + ")");               while ( inp == null )
           }                                                                        { try
        System.out.println ("Total weight: " + sumWeight);                             { File f = new File (lineIn);
        System.out.println ("Total value:   " + sumValue);                                inp = new Scanner (f);
   }                                                                                   }
                                                                                       catch (IOException e)
   public static void main ( String[] args ) throws Exception
                                                                                       { System.out.println ("Exception: " + e); }
   { int [] pack;
                                                                                       finally
      int [] weight, value;
                                                                                       { if (inp == null)
      int k, n, maxWeight;
                                                                                          { System.out.print ("Yo! Open failed for " + lineIn
      String lineIn = "";
                                                                                                  + "\nPlease enter a valid file name: ");
      Scanner inp = null;
                                                                                             System.out.flush();
      int sumValue = 0, sumWeight = 0;
                                                                                             lineIn = console.nextLine();
                                                                                             if ( lineIn.length() == 0 )
   // Debug option: program supports command-line argument of file name
                                                                                             { System.out.println ("NULL name; aborting!");
      if (args.length > 0)
                                                                                                System.exit(0);
      { lineIn = args[0];
                                                                                             }
         System.out.println ("Reading data from file " + lineIn);
                                                                                          }
      }
                                                                                       } // end try / catch / finally
      inp = openInput (lineIn);
      maxWeight = inp.nextInt();                                                    } // end while
      n = inp.nextInt();
                                                                                   return inp;
      weight = new int[n];
                                                                                } // end openInput
      value   = new int[n];
                                                                            }
      pack    = new int[n];
                                                                            /* Specimen run with DEBUG off
        for ( k = 0; k < n; k++ )
                                                                            Reading data from file BandP_2.txt
        { weight[k] = inp.nextInt();
                                                                            Optimal knapsack:
           value[k] = inp.nextInt();
                                                                            (2 used: 6, 18)
        }
                                                                            Total weight: 12
        knapSack (maxWeight, pack, weight, value);
                                                                            Total value:   36
        System.out.println ("Optimal knapsack:");
                                                                            Total method invocations: 31
        display(weight, value, pack);
                                                                            */

Printed on 2010-09-03 at 14:46