Skip to content

Commit

Permalink
working SetNumTheads in Python/Java/C#; Working SetHint in java/C#
Browse files Browse the repository at this point in the history
  • Loading branch information
Laurent Perron committed Jun 29, 2019
1 parent 5a33438 commit 8a4ae8b
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 3 deletions.
23 changes: 23 additions & 0 deletions ortools/linear_solver/csharp/VariableHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,27 @@ public partial class Variable {
}
}

// TODO(user): Try to move this code back to the .swig with @define macros.
public partial class MPVariableVector: IDisposable, System.Collections.IEnumerable
#if !SWIG_DOTNET_1
, System.Collections.Generic.IList<Variable>
#endif
{
// cast from C# MPVariable array
public static implicit operator MPVariableVector(Variable[] inVal) {
var outVal= new MPVariableVector();
foreach (Variable element in inVal) {
outVal.Add(element);
}
return outVal;
}

// cast to C# MPVariable array
public static implicit operator Variable[](MPVariableVector inVal) {
var outVal= new Variable[inVal.Count];
inVal.CopyTo(outVal);
return outVal;
}
}

} // namespace Google.OrTools.LinearSolver
31 changes: 31 additions & 0 deletions ortools/linear_solver/csharp/linear_solver.i
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ class MPSolutionResponse;
%template(MpDoubleVector) std::vector<double>;
VECTOR_AS_CSHARP_ARRAY(double, double, double, MpDoubleVector);

%define CONVERT_VECTOR(CTYPE, TYPE)
SWIG_STD_VECTOR_ENHANCED(CTYPE*);
%template(TYPE ## Vector) std::vector<CTYPE*>;
%enddef // CONVERT_VECTOR

CONVERT_VECTOR(operations_research::MPVariable, MPVariable)

#undef CONVERT_VECTOR

%ignoreall

%unignore operations_research;
Expand Down Expand Up @@ -147,6 +156,10 @@ VECTOR_AS_CSHARP_ARRAY(double, double, double, MpDoubleVector);
// Extend code.
%unignore operations_research::MPSolver::ExportModelAsLpFormat(bool);
%unignore operations_research::MPSolver::ExportModelAsMpsFormat(bool, bool);
%unignore operations_research::MPSolver::SetHint(
const std::vector<operations_research::MPVariable*>&,
const std::vector<double>&);
%unignore operations_research::MPSolver::SetNumThreads;
%extend operations_research::MPSolver {
std::string ExportModelAsLpFormat(bool obfuscated) {
operations_research::MPModelExportOptions options;
Expand All @@ -163,6 +176,24 @@ VECTOR_AS_CSHARP_ARRAY(double, double, double, MpDoubleVector);
$self->ExportModelToProto(&model);
return ExportModelAsMpsFormat(model, options).value_or("");
}

void SetHint(const std::vector<operations_research::MPVariable*>& variables,
const std::vector<double>& values) {
if (variables.size() != values.size()) {
LOG(FATAL) << "Different number of variables and values when setting "
<< "hint.";
}
std::vector<std::pair<const operations_research::MPVariable*, double> >
hint(variables.size());
for (int i = 0; i < variables.size(); ++i) {
hint[i] = std::make_pair(variables[i], values[i]);
}
$self->SetHint(hint);
}

bool SetNumThreads(int num_theads) {
return $self->SetNumThreads(num_theads).ok();
}
}

// MPVariable: writer API.
Expand Down
27 changes: 26 additions & 1 deletion ortools/linear_solver/java/linear_solver.i
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ typedef uint64_t uint64;
#include "ortools/linear_solver/model_exporter.h"
%}

%define CONVERT_VECTOR(CType, JavaType)
CONVERT_VECTOR_WITH_CAST(CType, JavaType, REINTERPRET_CAST,
com/google/ortools/linearsolver);
%enddef

CONVERT_VECTOR(operations_research::MPVariable, MPVariable);

#undef CONVERT_VECTOR

%typemap(javaimports) SWIGTYPE %{
import java.lang.reflect.*;
%}
Expand All @@ -75,11 +84,22 @@ import java.lang.reflect.*;
return ExportModelAsMpsFormat(model, options).value_or("");
}

/// Set a hint for solution.
///
/// If a feasible or almost-feasible solution to the problem is already known,
/// it may be helpful to pass it to the solver so that it can be used. A
/// solver that supports this feature will try to use this information to
/// create its initial feasible solution.
///
/// Note that it may not always be faster to give a hint like this to the
/// solver. There is also no guarantee that the solver will use this hint or
/// try to return a solution "close" to this assignment in case of multiple
/// optimal solutions.
void setHint(const std::vector<operations_research::MPVariable*>& variables,
const std::vector<double>& values) {
if (variables.size() != values.size()) {
LOG(FATAL) << "Different number of variables and values when setting "
<< "hint.";
<< "hint.";
}
std::vector<std::pair<const operations_research::MPVariable*, double> >
hint(variables.size());
Expand All @@ -88,6 +108,11 @@ import java.lang.reflect.*;
}
$self->SetHint(hint);
}

/// Sets the number of threads to be used by the solver.
bool setNumThreads(int num_theads) {
return $self->SetNumThreads(num_theads).ok();
}
}

// Add java code on MPSolver.
Expand Down
2 changes: 1 addition & 1 deletion ortools/linear_solver/linear_solver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ bool MPSolver::ExportModelAsMpsFormat(bool fixed_format, bool obfuscate,
// if (fixed_format) {
// LOG_EVERY_N_SEC(WARNING, 10)
// << "Fixed format is deprecated. Using free format instead.";
//
//

MPModelProto proto;
ExportModelToProto(&proto);
Expand Down
65 changes: 64 additions & 1 deletion ortools/linear_solver/python/linear_solver.i
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,40 @@ class MPSolutionResponse;
#include "ortools/linear_solver/model_exporter_swig_helper.h"
%}

// Actual conversions. This also includes the conversion to std::vector<Class>.
%define PY_CONVERT(Class)
%{

template<>
bool PyObjAs(PyObject *py_obj, operations_research::MPVariable** b) {
return SWIG_ConvertPtr(py_obj, reinterpret_cast<void**>(b),
SWIGTYPE_p_operations_research__MPVariable,
SWIG_POINTER_EXCEPTION) >= 0;
}

bool CanConvertTo ## Class(PyObject *py_obj) {
operations_research::Class* tmp;
return PyObjAs(py_obj, &tmp);
}

%}

%typemap(in) operations_research::Class* const {
if (!PyObjAs($input, &$1)) SWIG_fail;
}

%typecheck(SWIG_TYPECHECK_POINTER) operations_research::Class* const {
$1 = CanConvertTo ## Class($input);
if ($1 == 0) PyErr_Clear();
}

PY_LIST_OUTPUT_TYPEMAP(operations_research::Class*, CanConvertTo ## Class,
PyObjAs<operations_research::Class*>);
%enddef

PY_CONVERT(MPVariable);
#undef PY_CONVERT

namespace operations_research {

%pythoncode {
Expand Down Expand Up @@ -104,6 +138,36 @@ from ortools.linear_solver.linear_solver_natural_api import VariableExpr
return ExportModelAsMpsFormat(model, options).value_or("");
}

/// Set a hint for solution.
///
/// If a feasible or almost-feasible solution to the problem is already known,
/// it may be helpful to pass it to the solver so that it can be used. A
/// solver that supports this feature will try to use this information to
/// create its initial feasible solution.
///
/// Note that it may not always be faster to give a hint like this to the
/// solver. There is also no guarantee that the solver will use this hint or
/// try to return a solution "close" to this assignment in case of multiple
/// optimal solutions.
void SetHint(const std::vector<MPVariable*>& variables,
const std::vector<double>& values) {
if (variables.size() != values.size()) {
LOG(FATAL) << "Different number of variables and values when setting "
<< "hint.";
}
std::vector<std::pair<const operations_research::MPVariable*, double> >
hint(variables.size());
for (int i = 0; i < variables.size(); ++i) {
hint[i] = std::make_pair(variables[i], values[i]);
}
$self->SetHint(hint);
}

/// Sets the number of threads to be used by the solver.
bool SetNumThreads(int num_theads) {
return $self->SetNumThreads(num_theads).ok();
}

%pythoncode {
def Add(self, constraint, name=''):
if isinstance(constraint, bool):
Expand Down Expand Up @@ -274,7 +338,6 @@ PY_PROTO_TYPEMAP(ortools.linear_solver.linear_solver_pb2,
%unignore operations_research::MPSolver::NextSolution;
%unignore operations_research::MPSolver::ExportModelAsLpFormat;
%unignore operations_research::MPSolver::ExportModelAsMpsFormat;
%unignore operations_research::MPSolver::SetNumThreads;

// Expose very advanced parts of the MPSolver API. For expert users only.
%unignore operations_research::MPSolver::ComputeConstraintActivities;
Expand Down

0 comments on commit 8a4ae8b

Please sign in to comment.