cstsp.cs 4.04 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
// Copyright 2010-2018 Google LLC
// 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.Collections.Generic;
using Google.OrTools.ConstraintSolver;

class Tsp
{
  class RandomManhattan {
    public RandomManhattan(RoutingIndexManager manager, int size, int seed)
    {
      this.xs_ = new int[size];
      this.ys_ = new int[size];
      this.manager_ = manager;
      Random generator = new Random(seed);
      for (int i = 0; i < size; ++i)
      {
        xs_[i] = generator.Next(1000);
        ys_[i] = generator.Next(1000);
      }
    }

    public long Call(long first_index, long second_index) {
      int first_node = manager_.IndexToNode(first_index);
      int second_node = manager_.IndexToNode(second_index);
      return Math.Abs(xs_[first_node] - xs_[second_node]) +
          Math.Abs(ys_[first_node] - ys_[second_node]);
    }

    private readonly int[] xs_;
    private readonly int[] ys_;
    private readonly RoutingIndexManager manager_;
  };

  static void Solve(int size, int forbidden, int seed)
  {
    RoutingIndexManager manager = new RoutingIndexManager(size, 1, 0);
    RoutingModel routing = new RoutingModel(manager);

    // Setting the cost function.
    // Put a permanent callback to the distance accessor here. The callback
    // has the following signature: ResultCallback2<int64, int64, int64>.
    // The two arguments are the from and to node inidices.
    RandomManhattan distances = new RandomManhattan(manager, size, seed);
    routing.SetArcCostEvaluatorOfAllVehicles(
        routing.RegisterTransitCallback(distances.Call));

    // Forbid node connections (randomly).
    Random randomizer = new Random();
    long forbidden_connections = 0;
    while (forbidden_connections < forbidden) {
      long from = randomizer.Next(size - 1);
      long to = randomizer.Next(size - 1) + 1;
      if (routing.NextVar(from).Contains(to)) {
        Console.WriteLine("Forbidding connection {0} -> {1}", from, to);
        routing.NextVar(from).RemoveValue(to);
        ++forbidden_connections;
      }
    }

    // Add dummy dimension to test API.
    routing.AddDimension(
        routing.RegisterUnaryTransitCallback((long index) => {return 1;}),
        size + 1,
        size + 1,
        true,
        "dummy");

    // Solve, returns a solution if any (owned by RoutingModel).
    RoutingSearchParameters search_parameters =
        operations_research_constraint_solver.DefaultRoutingSearchParameters();
    // Setting first solution heuristic (cheapest addition).
    search_parameters.FirstSolutionStrategy =
        FirstSolutionStrategy.Types.Value.PathCheapestArc;

    Assignment solution = routing.SolveWithParameters(search_parameters);
    Console.WriteLine("Status = {0}", routing.GetStatus());
    if (solution != null) {
      // Solution cost.
      Console.WriteLine("Cost = {0}", solution.ObjectiveValue());
      // Inspect solution.
      // Only one route here; otherwise iterate from 0 to routing.vehicles() - 1
      int route_number = 0;
      for (long node = routing.Start(route_number);
           !routing.IsEnd(node);
           node = solution.Value(routing.NextVar(node))) {
        Console.Write("{0} -> ", node);
      }
      Console.WriteLine("0");
    }
  }

  public static void Main(String[] args)
  {
    int size = 10;
    if (args.Length > 0) {
      size = Convert.ToInt32(args[0]);
    }
    int forbidden = 0;
    if (args.Length > 1) {
      forbidden = Convert.ToInt32(args[1]);
    }
    int seed = 0;
    if (args.Length > 2) {
      seed = Convert.ToInt32(args[2]);
    }

    Solve(size, forbidden, seed);
  }
}