diff --git a/examples/com/google/ortools/constraintsolver/samples/Tsp.java b/examples/com/google/ortools/constraintsolver/samples/Tsp.java new file mode 100644 index 0000000000..830581c30b --- /dev/null +++ b/examples/com/google/ortools/constraintsolver/samples/Tsp.java @@ -0,0 +1,125 @@ +// +// Copyright 2012 Google +// +// 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. + + +package com.google.ortools.constraintsolver.samples; + +import java.io.*; +import java.util.*; +import java.text.*; + +import com.google.ortools.constraintsolver.Assignment; +import com.google.ortools.constraintsolver.NodeEvaluator2; +import com.google.ortools.constraintsolver.RoutingModel; + +class Tsp { + + static { + System.loadLibrary("jniconstraintsolver"); + } + + static class RandomManhattan extends NodeEvaluator2 { + public RandomManhattan(int size, int seed) { + this.xs = new int[size]; + this.ys = new int[size]; + Random generator = new Random(seed); + for (int i = 0; i < size; ++i) { + xs[i] = generator.nextInt(1000); + ys[i] = generator.nextInt(1000); + } + } + + @Override + public long run(int firstIndex, int secondIndex) { + return Math.abs(xs[firstIndex] - xs[secondIndex]) + + Math.abs(ys[firstIndex] - ys[secondIndex]); + } + + private int[] xs; + private int[] ys; + } + + static class ConstantCallback extends NodeEvaluator2 { + @Override + public long run(int firstIndex, int secondIndex) { + return 1; + } + } + + static void solve(int size, int forbidden, int seed) + { + RoutingModel routing = new RoutingModel(size, 1); + // Setting first solution heuristic (cheapest addition). + routing.setFirstSolutionStrategy(RoutingModel.ROUTING_PATH_CHEAPEST_ARC); + + // Setting the cost function. + // Put a permanent callback to the distance accessor here. The callback + // has the following signature: ResultCallback2. + // The two arguments are the from and to node inidices. + RandomManhattan distances = new RandomManhattan(size, seed); + routing.setCost(distances); + + // Forbid node connections (randomly). + Random randomizer = new Random(); + long forbidden_connections = 0; + while (forbidden_connections < forbidden) { + long from = randomizer.nextInt(size - 1); + long to = randomizer.nextInt(size - 1) + 1; + if (routing.nextVar(from).contains(to)) { + System.out.println("Forbidding connection " + from + " -> " + to); + routing.nextVar(from).removeValue(to); + ++forbidden_connections; + } + } + + // Add dummy dimension to test API. + routing.addDimension(new ConstantCallback(), size + 1, size + 1, "dummy"); + + // Solve, returns a solution if any (owned by RoutingModel). + Assignment solution = routing.solve(); + if (solution != null) { + // Solution cost. + System.out.println("Cost = " + 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))) { + System.out.print("" + node + " -> "); + } + System.out.println("0"); + } + } + + public static void main(String[] args) throws Exception { + int size = 10; + if (args.length > 0) { + size = Integer.parseInt(args[0]); + } + + int forbidden = 0; + if (args.length > 1) { + forbidden = Integer.parseInt(args[1]); + } + + int seed = 0; + if (args.length > 2) { + seed = Integer.parseInt(args[2]); + } + + solve(size, forbidden, seed); + } +} diff --git a/makefiles/Makefile.java.mk b/makefiles/Makefile.java.mk index c3e44a91cd..7467765630 100644 --- a/makefiles/Makefile.java.mk +++ b/makefiles/Makefile.java.mk @@ -28,8 +28,9 @@ clean_java: # javacp javacp: $(LIB_DIR)/com.google.ortools.constraintsolver.jar $(LIB_DIR)/$(LIBPREFIX)jniconstraintsolver.$(JNILIBEXT) -$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/constraint_solver.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/data.swig $(SRC_DIR)/constraint_solver/constraint_solver.h - $(SWIG_BINARY) -I$(INC_DIR) -c++ -java -o $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc -package com.google.ortools.constraintsolver -outdir $(GEN_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver $(SRC_DIR)/constraint_solver$Sconstraint_solver.swig + +$(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc: $(SRC_DIR)/constraint_solver/constraint_solver.swig $(SRC_DIR)/constraint_solver/routing.swig $(SRC_DIR)/base/base.swig $(SRC_DIR)/util/data.swig $(SRC_DIR)/constraint_solver/constraint_solver.h + $(SWIG_BINARY) -I$(INC_DIR) -c++ -java -o $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc -package com.google.ortools.constraintsolver -outdir $(GEN_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver $(SRC_DIR)$Sconstraint_solver$Srouting.swig $(OBJ_DIR)/constraint_solver_java_wrap.$O: $(GEN_DIR)/constraint_solver/constraint_solver_java_wrap.cc $(CCC) $(JNIFLAGS) $(JAVA_INC) -c $(GEN_DIR)$Sconstraint_solver$Sconstraint_solver_java_wrap.cc $(OBJ_OUT)constraint_solver_java_wrap.$O @@ -38,8 +39,8 @@ $(LIB_DIR)/com.google.ortools.constraintsolver.jar: $(GEN_DIR)/constraint_solver $(JAVAC_BIN) -d $(OBJ_DIR) $(SRC_DIR)/com$Sgoogle$Sortools$Sconstraintsolver$S*.java $(GEN_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver$S*.java $(JAR_BIN) cf $(LIB_DIR)$Scom.google.ortools.constraintsolver.jar -C $(OBJ_DIR) $Scom$Sgoogle$Sortools$Sconstraintsolver -$(LIB_DIR)/$(LIBPREFIX)jniconstraintsolver.$(JNILIBEXT): $(OBJ_DIR)/constraint_solver_java_wrap.$O $(CP_DEPS) - $(LD) $(LDOUT)$(LIB_DIR)$S$(LIBPREFIX)jniconstraintsolver.$(JNILIBEXT) $(OBJ_DIR)$Sconstraint_solver_java_wrap.$O $(CP_LNK) $(LDFLAGS) +$(LIB_DIR)/$(LIBPREFIX)jniconstraintsolver.$(JNILIBEXT): $(OBJ_DIR)/constraint_solver_java_wrap.$O $(ROUTING_DEPS) + $(LD) $(LDOUT)$(LIB_DIR)$S$(LIBPREFIX)jniconstraintsolver.$(JNILIBEXT) $(OBJ_DIR)$Sconstraint_solver_java_wrap.$O $(ROUTING_LNK) $(LDFLAGS) # Java CP Examples @@ -196,6 +197,13 @@ $(OBJ_DIR)/com/google/ortools/constraintsolver/samples/Sudoku.class: javacp $(EX run_Sudoku: compile_Sudoku $(JAVA_BIN) -Djava.library.path=$(LIB_DIR) -cp $(OBJ_DIR)$(CPSEP)$(LIB_DIR)$Scom.google.ortools.constraintsolver.jar com.google.ortools.constraintsolver.samples.Sudoku +compile_Tsp: $(OBJ_DIR)/com/google/ortools/constraintsolver/samples/Tsp.class + +$(OBJ_DIR)/com/google/ortools/constraintsolver/samples/Tsp.class: javacp $(EX_DIR)/com/google/ortools/constraintsolver/samples/Tsp.java + $(JAVAC_BIN) -d $(OBJ_DIR) -cp $(LIB_DIR)$Scom.google.ortools.constraintsolver.jar $(EX_DIR)$Scom$Sgoogle$Sortools$Sconstraintsolver$Ssamples$STsp.java + +run_Tsp: compile_Tsp + $(JAVA_BIN) -Djava.library.path=$(LIB_DIR) -cp $(OBJ_DIR)$(CPSEP)$(LIB_DIR)$Scom.google.ortools.constraintsolver.jar com.google.ortools.constraintsolver.samples.Tsp $(ARGS) compile_Xkcd: $(OBJ_DIR)/com/google/ortools/constraintsolver/samples/Xkcd.class diff --git a/makefiles/Makefile.test.unix b/makefiles/Makefile.test.unix index bb29c06e90..02c27bdc51 100644 --- a/makefiles/Makefile.test.unix +++ b/makefiles/Makefile.test.unix @@ -17,7 +17,7 @@ test_python: python PYTHONPATH=$(OR_ROOT_FULL)/src python$(PYTHONVERSION) $(EX_DIR)/python/linear_programming.py PYTHONPATH=$(OR_ROOT_FULL)/src python$(PYTHONVERSION) $(EX_DIR)/python/integer_programming.py -test_java: java run_RabbitsPheasants run_FlowExample run_LinearProgramming run_IntegerProgramming run_Knapsack +test_java: java run_RabbitsPheasants run_FlowExample run_Tsp run_LinearProgramming run_IntegerProgramming run_Knapsack # csharp test test_csharp: $(CSHARPEXE) $(BIN_DIR)/testlp.exe $(BIN_DIR)/testcp.exe diff --git a/makefiles/Makefile.test.win b/makefiles/Makefile.test.win index 102fb0ba55..bca7206468 100644 --- a/makefiles/Makefile.test.win +++ b/makefiles/Makefile.test.win @@ -17,7 +17,7 @@ test_python: python set PYTHONPATH=$(OR_ROOT_FULL)\\src && $(WINDOWS_PYTHON_PATH)\\python $(EX_DIR)\\python\\linear_programming.py set PYTHONPATH=$(OR_ROOT_FULL)\\src && $(WINDOWS_PYTHON_PATH)\\python $(EX_DIR)\python\\integer_programming.py -test_java: java run_RabbitsPheasants run_FlowExample run_LinearProgramming run_IntegerProgramming run_Knapsack +test_java: java run_RabbitsPheasants run_FlowExample run_Tsp run_LinearProgramming run_IntegerProgramming run_Knapsack # csharp test test_csharp: $(CSHARPEXE) $(BIN_DIR)/testlp.exe $(BIN_DIR)/testcp.exe diff --git a/src/constraint_solver/routing.swig b/src/constraint_solver/routing.swig index e754eb0e8e..7f90b7b8d3 100644 --- a/src/constraint_solver/routing.swig +++ b/src/constraint_solver/routing.swig @@ -193,7 +193,7 @@ class NodeEvaluator2 { return run(i.value(), j.value()); } virtual int64 run(int i, int j) = 0; - RoutingModel::NodeEvaluator2* GetPermanentCallback() { + RoutingModel::NodeEvaluator2* getPermanentCallback() { return NewPermanentCallback(this, &NodeEvaluator2::runAux); } virtual ~NodeEvaluator2() {} @@ -205,11 +205,11 @@ class NodeEvaluator2 { public: virtual ~NodeEvaluator2(); virtual int64 run(int i, int j) = 0; - operations_research::RoutingModel::NodeEvaluator2* GetPermanentCallback(); + operations_research::RoutingModel::NodeEvaluator2* getPermanentCallback(); }; %typemap(jstype) RoutingModel::NodeEvaluator2* "NodeEvaluator2"; -%typemap(javain) RoutingModel::NodeEvaluator2* "SWIGTYPE_p_ResultCallback2T_long_long__RoutingModel_NodeIndex__RoutingModel_NodeIndex_t.getCPtr($javainput.GetPermanentCallback())"; +%typemap(javain) RoutingModel::NodeEvaluator2* "SWIGTYPE_p_ResultCallback2T_long_long__RoutingModel_NodeIndex__RoutingModel_NodeIndex_t.getCPtr($javainput.getPermanentCallback())"; #endif // SWIGJAVA #ifdef SWIGCSHARP %module(directors="1") main @@ -233,7 +233,7 @@ class NodeEvaluator2 { class NodeEvaluator2 { public: virtual ~NodeEvaluator2(); - virtual int64 Run(int i,int j) = 0; + virtual int64 Run(int i, int j) = 0; operations_research::RoutingModel::NodeEvaluator2* GetPermanentCallback(); };