ski_assignment.cs 3.73 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
//
// Copyright 2012 Hakan Kjellerstrand
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using Google.OrTools.ConstraintSolver;

public class SkiAssignment
{
  /**
   *
   * Ski assignment in Google CP Solver.
   *
   * From   Jeffrey Lee Hellrung, Jr.:
   * PIC 60, Fall 2008 Final Review, December 12, 2008
   * http://www.math.ucla.edu/~jhellrun/course_files/Fall%25202008/PIC%252060%2520-%2520Data%2520Structures%2520and%2520Algorithms/final_review.pdf
   * """
   * 5. Ski Optimization! Your job at Snapple is pleasant but in the winter
   * you've decided to become a ski bum. You've hooked up with the Mount
   * Baldy Ski Resort. They'll let you ski all winter for free in exchange
   * for helping their ski rental shop with an algorithm to assign skis to
   * skiers. Ideally, each skier should obtain a pair of skis whose height
   * matches his or her own height exactly. Unfortunately, this is generally
   * not possible. We define the disparity between a skier and his or her
   * skis to be the absolute value of the difference between the height of
   * the skier and the pair of skis. Our objective is to find an assignment
   * of skis to skiers that minimizes the sum of the disparities.
   * ...
   * Illustrate your algorithm by explicitly filling out the A[i, j] table
   * for the following sample data:
   *  - Ski heights  : 1, 2, 5, 7, 13, 21.
   *  - Skier heights: 3, 4, 7, 11, 18.
   * """
   *
   * Also see http://www.hakank.org/or-tools/ski_assignment.py
   *

   */
  private static void Solve()
  {
    Solver solver = new Solver("SkiAssignment");

    //
    // Data
    //
    int num_skis = 6;
    int num_skiers = 5;
    int[] ski_heights = {1, 2, 5, 7, 13, 21};
    int[] skier_heights = {3, 4, 7, 11, 18};

    //
    // Decision variables
    //
    IntVar[] x = solver.MakeIntVarArray(num_skiers, 0, num_skis-1, "x");


    //
    // Constraints
    //
    solver.Add(x.AllDifferent());

    IntVar[] z_tmp = new IntVar[num_skiers];
    for(int i = 0; i < num_skiers; i++) {
      z_tmp[i] = (ski_heights.Element(x[i]) - skier_heights[i]).Abs().Var();
    }

    //    IntVar z = solver.MakeIntVar(0, ski_heights.Sum(), "z");
    //    solver.Add(z_tmp.Sum() == z);
    // The direct cast from IntExpr to IntVar is potentially faster than
    // the above code.
    IntVar z = z_tmp.Sum().VarWithName("z");

    //
    // Objective
    //
    OptimizeVar obj = z.Minimize(1);

    //
    // Search
    //
    DecisionBuilder db = solver.MakePhase(x,
                                          Solver.CHOOSE_FIRST_UNBOUND,
                                          Solver.INT_VALUE_DEFAULT);

    solver.NewSearch(db, obj);

    while (solver.NextSolution()) {
      Console.Write("z: {0} x: ", z.Value());
      for(int i = 0; i < num_skiers; i++) {
        Console.Write(x[i].Value() + " ");
      }
      Console.WriteLine();
    }

    Console.WriteLine("\nSolutions: {0}", solver.Solutions());
    Console.WriteLine("WallTime: {0}ms", solver.WallTime());
    Console.WriteLine("Failures: {0}", solver.Failures());
    Console.WriteLine("Branches: {0} ", solver.Branches());

    solver.EndSearch();

  }

  public static void Main(String[] args)
  {
    Solve();
  }
}