diff --git a/examples/tests/RoutingSolverTests.cs b/examples/tests/RoutingSolverTests.cs index 72fd8129c2..e5c127a923 100644 --- a/examples/tests/RoutingSolverTests.cs +++ b/examples/tests/RoutingSolverTests.cs @@ -24,8 +24,7 @@ namespace Google.OrTools.Tests }); // Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); - if (callGC) - { + if (callGC) { GC.Collect(); } // Setting first solution heuristic. @@ -36,5 +35,159 @@ namespace Google.OrTools.Tests // 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+4)-> 0 := +8 Assert.Equal(8, solution.ObjectiveValue()); } + + [Fact] + public void TestTransitMatrix() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + long[][] matrix = new long[][] { + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + }; + int transitCallbackIndex = routing.RegisterTransitMatrix(matrix); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + // 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5 + Assert.Equal(5, solution.ObjectiveValue()); + } + + [Fact] + public void TestTransitCallback() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + int transitCallbackIndex = routing.RegisterTransitCallback( + (long fromIndex, long toIndex) => { + // Convert from routing variable Index to distance matrix NodeIndex. + var fromNode = manager.IndexToNode(fromIndex); + var toNode = manager.IndexToNode(toIndex); + return Math.Abs(toNode - fromNode); + }); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + Assert.Equal(8, solution.ObjectiveValue()); + } + + [Fact] + public void TestMatrixDimension() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + long[][] matrix = new long[][] { + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + new long[] {1, 1, 1, 1, 1}, + }; + IntBoolPair result = routing.AddMatrixDimension( + matrix, + /*capacity=*/10, + /*fix_start_cumul_to_zero=*/true, + "Dimension"); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(result.first); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + // 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5 + Assert.Equal(5, solution.ObjectiveValue()); + } + + [Fact] + public void TestUnaryTransitVector() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + long[] vector = {1, 1, 1, 1, 1}; + int transitCallbackIndex = routing.RegisterUnaryTransitVector(vector); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + // 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5 + Assert.Equal(5, solution.ObjectiveValue()); + } + + [Fact] + public void TestUnaryTransitCallback() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + int transitCallbackIndex = routing.RegisterUnaryTransitCallback( + (long fromIndex) => { + // Convert from routing variable Index to distance matrix NodeIndex. + var fromNode = manager.IndexToNode(fromIndex); + return fromNode+1; + }); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + // 0 --(+1)-> 1 --(+2)-> 2 --(+3)-> 3 --(+4)-> 4 --(+5)-> 0 := +15 + Assert.Equal(15, solution.ObjectiveValue()); + } + + [Fact] + public void TestVectorDimension() + { + // Create Routing Index Manager + RoutingIndexManager manager = new RoutingIndexManager(5 /*locations*/, 1 /*vehicle*/, 0 /*depot*/); + // Create Routing Model. + RoutingModel routing = new RoutingModel(manager); + // Create a distance callback. + long[] vector = new long[] {1, 1, 1, 1, 1}; + IntBoolPair result = routing.AddVectorDimension( + vector, + /*capacity=*/10, + /*fix_start_cumul_to_zero=*/true, + "Dimension"); + // Define cost of each arc. + routing.SetArcCostEvaluatorOfAllVehicles(result.first); + // Setting first solution heuristic. + RoutingSearchParameters searchParameters = + operations_research_constraint_solver.DefaultRoutingSearchParameters(); + searchParameters.FirstSolutionStrategy = FirstSolutionStrategy.Types.Value.PathCheapestArc; + Assignment solution = routing.SolveWithParameters(searchParameters); + // 0 --(+1)-> 1 --(+1)-> 2 --(+1)-> 3 --(+1)-> 4 --(+1)-> 0 := +5 + Assert.Equal(5, solution.ObjectiveValue()); + } } } // namespace Google.OrTools.Tests diff --git a/ortools/constraint_solver/csharp/routing.i b/ortools/constraint_solver/csharp/routing.i index 2bb00fab78..ec53160680 100644 --- a/ortools/constraint_solver/csharp/routing.i +++ b/ortools/constraint_solver/csharp/routing.i @@ -12,6 +12,9 @@ // limitations under the License. // TODO(user): Refactor this file to adhere to the SWIG style guide. +%include "std_pair.i" +%template(IntBoolPair) std::pair; + %include "ortools/constraint_solver/csharp/constraint_solver.i" %include "ortools/constraint_solver/csharp/routing_types.i" %include "ortools/constraint_solver/csharp/routing_index_manager.i" @@ -81,6 +84,12 @@ namespace operations_research { %} // Ignored: %ignore RoutingModel::AddDimensionDependentDimensionWithVehicleCapacity; + +%ignore RoutingModel::RegisterUnaryTransitVector( + std::vector values); +%ignore RoutingModel::RegisterTransitMatrix( + std::vector > values); + %ignore RoutingModel::AddVectorDimension( std::vector values, int64 capacity, @@ -93,20 +102,29 @@ namespace operations_research { const std::string& name); %extend RoutingModel { - int AddVectorDimension( + int RegisterUnaryTransitVector( + const std::vector& values) { + return $self->RegisterUnaryTransitVector(values); + } + int RegisterTransitMatrix( + const std::vector >& values) { + return $self->RegisterTransitMatrix(values); + } + + std::pair AddVectorDimension( const std::vector& values, int64 capacity, bool fix_start_cumul_to_zero, const std::string& name) { - return $self->AddVectorDimension(values, capacity, fix_start_cumul_to_zero, name).first; + return $self->AddVectorDimension(values, capacity, fix_start_cumul_to_zero, name); } - int AddMatrixDimension( + std::pair AddMatrixDimension( const std::vector >& values, int64 capacity, bool fix_start_cumul_to_zero, const std::string& name) { - return $self->AddMatrixDimension(values, capacity, fix_start_cumul_to_zero, name).first; + return $self->AddMatrixDimension(values, capacity, fix_start_cumul_to_zero, name); } }