MPSolver can accept protocol buffers as input and as output, examples in examples/linear_solver_example_with_protocol_buffers.cc

This commit is contained in:
lperron@google.com
2011-07-13 23:59:27 +00:00
parent 440d9b4a15
commit 5880a2776d
6 changed files with 116 additions and 7 deletions

View File

@@ -48,7 +48,8 @@ cpexe: $(CPBINARIES)
LPBINARIES = \
integer_solver_example$E \
linear_solver_example$E
linear_solver_example$E \
linear_solver_example_with_protocol_buffers$E
lpexe: $(LPBINARIES)
@@ -492,6 +493,12 @@ objs/linear_solver_example.$O: examples/linear_solver_example.cc
linear_solver_example$E: $(LP_LIBS) $(BASE_LIBS) objs/linear_solver_example.$O
$(CCC) $(CFLAGS) $(LDFLAGS) objs/linear_solver_example.$O $(LP_LIBS) $(BASE_LIBS) $(LDLPDEPS) $(EXEOUT)linear_solver_example$E
objs/linear_solver_example_with_protocol_buffers.$O: examples/linear_solver_example_with_protocol_buffers.cc
$(CCC) $(CFLAGS) -c examples/linear_solver_example_with_protocol_buffers.cc $(OBJOUT)objs/linear_solver_example_with_protocol_buffers.$O
linear_solver_example_with_protocol_buffers$E: $(LP_LIBS) $(BASE_LIBS) objs/linear_solver_example_with_protocol_buffers.$O
$(CCC) $(CFLAGS) $(LDFLAGS) objs/linear_solver_example_with_protocol_buffers.$O $(LP_LIBS) $(BASE_LIBS) $(LDLPDEPS) $(EXEOUT)linear_solver_example_with_protocol_buffers$E
objs/integer_solver_example.$O: examples/integer_solver_example.cc
$(CCC) $(CFLAGS) -c examples/integer_solver_example.cc $(OBJOUT)objs/integer_solver_example.$O

View File

@@ -28,6 +28,7 @@
#include "base/map-util.h"
#include "base/stl_util.h"
#include "base/hash.h"
#include "linear_solver/linear_solver.pb.h"
DEFINE_string(solver_write_model, "", "path of the file to write the model to");
@@ -503,7 +504,8 @@ void MPSolver::ExportModel(MPModelProto* model) const {
// Encode current solution in a solution response protocol buffer.
void MPSolver::FillSolutionResponse(MPSolutionResponse* response) const {
CHECK_NOTNULL(response);
if (response->has_result_status() ||
if ((response->has_result_status() &&
response->result_status() != MPSolutionResponse::NOT_SOLVED) ||
response->has_objective_value() ||
response->solution_values_size() > 0) {
LOG(WARNING) << "The solution response is not empty, "

View File

@@ -286,8 +286,6 @@ class MPSolver {
virtual ~MPSolver();
// ----- Methods using protocol buffers -----
#ifndef SWIG
// TODO(user): fix swig support.
// Loads model from protocol buffer.
LoadStatus LoadModel(const MPModelProto& model);
@@ -304,7 +302,6 @@ class MPSolver {
// of MPSolver, MPModelRequest.OptimizationProblemType is ignored.
void SolveWithProtocolBuffers(const MPModelRequest& model_request,
MPSolutionResponse* response);
#endif
// ----- Init and Clear -----
void Init() {} // To remove.

View File

@@ -14,6 +14,8 @@
// Linear solver Stubby services
syntax = "proto2";
option java_package = "com.google.ortools.linearsolver";
option java_multiple_files = true;
package operations_research;

View File

@@ -11,11 +11,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
%include "base/base.swig"
%include base/base.swig
%include util/data.swig
// Include the file we want to wrap a first time.
%{
#include "linear_solver/linear_solver.h"
#include "linear_solver/linear_solver.pb.h"
%}
#ifdef SWIGPYTHON
@@ -32,6 +34,12 @@
%ignore MakeNumVarArray;
%ignore MakeIntVarArray;
%ignore MakeBoolVarArray;
// The following 3 methods that use protocol buffers as output
// arguments are ignored as they are too difficult to wrap and there
// is no immediate use case.
%ignore ExportModel;
%ignore SolveWithProtocolBuffers;
%ignore FillSolutionResponse;
namespace operations_research {
%pythoncode {
@@ -347,6 +355,7 @@ class LinearConstraint(object):
#endif
#ifdef SWIGJAVA
%module(directors="1") operations_research;
namespace operations_research {
@@ -392,6 +401,7 @@ namespace operations_research {
%rename (clearObjective) MPSolver::ClearObjective;
%rename (init) MPSolver::Init;
%rename (isLpFormat) MPSolver::IsLPFormat;
%rename (loadModel) MPSolver::LoadModel;
%rename (makeBoolVar) MPSolver::MakeBoolVar;
%rename (makeIntVar) MPSolver::MakeIntVar;
%rename (makeNumVar) MPSolver::MakeNumVar;
@@ -415,11 +425,19 @@ namespace operations_research {
%rename (timeLimit) MPSolver::time_limit;
%rename (wallTime) MPSolver::wall_time;
%rename (writeModelFilename) MPSolver::write_model_filename;
// Ignore code on MPSolver.
// Ignore code on MPSolver, see replacement java code below.
%ignore MPSolver::MakeVarArray;
%ignore MPSolver::MakeNumVarArray;
%ignore MPSolver::MakeIntVarArray;
%ignore MPSolver::MakeBoolVarArray;
// The following 3 methods that use protocol buffers as output
// arguments are replaced by methods that return a protocol buffer,
// see code below.
%ignore MPSolver::ExportModel;
%ignore MPSolver::FillSolutionResponse;
%ignore MPSolver::SolveWithProtocolBuffers;
// Add java code on MPSolver.
%typemap(javacode) MPSolver %{
public MPVariable[] makeVarArray(int count,
@@ -475,6 +493,7 @@ namespace operations_research {
return makeVarArray(count, 0.0, 1.0, true, var_name);
}
%}
} // namespace operations_research
#endif // SWIGJAVA

View File

@@ -256,6 +256,12 @@ static bool PyCallbackBool(PyObject* pyfunc) {
#endif // SWIGPYTHON
#if defined(SWIGJAVA)
%{
#include "base/jniutil.h"
#include "base/scoped_ptr.h"
%}
%module(directors="1") main
%feature("director") LongResultCallback1;
%feature("director") LongResultCallback2;
@@ -395,4 +401,80 @@ class LongResultCallback3 {
$1 = &result;
}
// SWIG macros to be used in generating Java wrappers for C++ protocol
// message parameters. Each protocol message is serialized into
// byte[] before passing into (or returning from) C++ code.
// If the C++ function expects an input protocol message:
// foo(const MyProto* message,...)
// Use PROTO_INPUT macro:
// PROTO_INPUT(MyProto, com.google.proto.protos.test.MyProto, message)
//
// if the C++ function returns a protocol message:
// MyProto* foo();
// Use PROTO2_RETURN_AND_DELETE macro:
// PROTO2_RETURN_AND_DELETE(MyProto, com.google.proto.protos.test.MyProto)
// Passing each protocol message from Java to C++ by value. Each ProtocolMessage
// is serialized into byte[] when it is passed from Java to C++, the C++ code
// deserializes into C++ native protocol message.
//
// @param CppProtoType the fully qualified C++ protocol message type
// @param JavaProtoType the corresponding fully qualified Java protocol message
// type
// @param param_name the parameter name
%define PROTO_INPUT(CppProtoType, JavaProtoType, param_name)
%typemap(jni) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "jbyteArray"
%typemap(jtype) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "byte[]"
%typemap(jstype) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "JavaProtoType"
%typemap(javain) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "$javainput.toByteArray()"
%typemap(in) PROTO_TYPE* INPUT (CppProtoType temp),
PROTO_TYPE& INPUT (CppProtoType temp) {
int proto_size = 0;
scoped_array<char> proto_buffer(
JNIUtil::MakeCharArray(jenv, $input, &proto_size));
bool parsed_ok = temp.ParseFromArray(proto_buffer.get(), proto_size);
if (!parsed_ok) {
SWIG_JavaThrowException(jenv,
SWIG_JavaRuntimeException,
"Unable to parse CppProtoType protocol message.");
}
$1 = &temp;
}
%apply PROTO_TYPE& INPUT { const CppProtoType& param_name }
%apply PROTO_TYPE& INPUT { CppProtoType& param_name }
%apply PROTO_TYPE* INPUT { const CppProtoType* param_name }
%apply PROTO_TYPE* INPUT { CppProtoType* param_name }
%enddef // end PROTO_INPUT
%define PROTO2_RETURN(CppProtoType, JavaProtoType, deleteCppReturn)
%typemap(jni) CppProtoType* "jbyteArray"
%typemap(jtype) CppProtoType* "byte[]"
%typemap(jstype) CppProtoType* "JavaProtoType"
%typemap(javaout) CppProtoType* {
byte[] buf = $jnicall;
if (buf == null || buf.length == 0) {
return null;
}
try {
return JavaProtoType.parseFrom(buf);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw new RuntimeException(
"Unable to parse JavaProtoType protocol message.");
}
}
%typemap(out) CppProtoType* {
scoped_array<char> buf(new char[$1->ByteSize()]);
$1->SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(buf.get()));
$result = JNIUtil::MakeJByteArray(jenv, buf.get(), $1->ByteSize());
if (deleteCppReturn) {
// To prevent a memory leak.
delete $1;
$1 = NULL;
}
}
%enddef // end PROTO2_RETURN_AND_DELETE
#endif // SWIGJAVA