Bind ValidateCpModel and SolutionIsFeasible from cp_model_checker.h

Fixes #22
This commit is contained in:
Guillaume Pinot
2021-09-22 10:07:28 +02:00
committed by Guillaume P
parent 609149dc12
commit 7ecf0c3fc2
5 changed files with 108 additions and 1 deletions
+19
View File
@@ -715,6 +715,25 @@ impl CpModelBuilder {
ffi::cp_model_stats(self.proto())
}
/// Verifies that the given model satisfies all the properties
/// described in the proto comments. Returns an empty string if it is
/// the case, otherwise fails at the first error and returns a
/// human-readable description of the issue.
///
/// # Example
///
/// ```
/// # use cp_sat::builder::CpModelBuilder;
/// # use cp_sat::proto::CpSolverStatus;
/// let mut model = CpModelBuilder::default();
/// let x = model.new_int_var([(0, -1)]);
/// model.maximize(x);
/// assert!(!model.validate_cp_model().is_empty());
/// ```
pub fn validate_cp_model(&self) -> String {
ffi::validate_cp_model(self.proto())
}
/// Solves the model, and returns the corresponding [proto::CpSolverResponse].
///
/// # Example
+31
View File
@@ -1,6 +1,7 @@
#include <iostream>
#include <ortools/sat/cp_model.h>
#include <ortools/sat/cp_model_checker.h>
namespace sat = operations_research::sat;
@@ -73,3 +74,33 @@ cp_sat_wrapper_cp_solver_response_stats(
const std::string stats = sat::CpSolverResponseStats(response, has_objective);
return strdup(stats.c_str());
}
extern "C" char*
cp_sat_wrapper_validate_cp_model(unsigned char* model_buf, size_t model_size) {
sat::CpModelProto model;
const bool res = model.ParseFromArray(model_buf, model_size);
assert(res);
const std::string stats = sat::ValidateCpModel(model);
return strdup(stats.c_str());
}
extern "C" bool
cp_sat_wrapper_solution_is_feasible(
unsigned char* model_buf,
size_t model_size,
const int64_t* solution_buf,
size_t solution_size)
{
sat::CpModelProto model;
const bool res = model.ParseFromArray(model_buf, model_size);
assert(res);
std::vector<int64_t> variable_values;
variable_values.reserve(solution_size);
for (size_t i = 0; i < solution_size; ++i) {
variable_values.push_back(solution_buf[i]);
}
return sat::SolutionIsFeasible(model, variable_values);
}
+55
View File
@@ -22,6 +22,13 @@ extern "C" {
response_size: usize,
has_objective: bool,
) -> *mut c_char;
fn cp_sat_wrapper_validate_cp_model(model_buf: *const u8, model_size: usize) -> *mut c_char;
fn cp_sat_wrapper_solution_is_feasible(
model_buf: *const u8,
model_size: usize,
solution_buf: *const i64,
solution_size: usize,
) -> bool;
}
/// Solves the given [CpModelProto][crate::proto::CpModelProto] and
@@ -101,3 +108,51 @@ pub fn cp_solver_response_stats(response: &proto::CpSolverResponse, has_objectiv
unsafe { libc::free(char_ptr as _) };
res
}
/// Verifies that the given model satisfies all the properties
/// described in the proto comments. Returns an empty string if it is
/// the case, otherwise fails at the first error and returns a
/// human-readable description of the issue.
pub fn validate_cp_model(model: &proto::CpModelProto) -> String {
let mut model_buf = Vec::default();
model.encode(&mut model_buf).unwrap();
let char_ptr = unsafe { cp_sat_wrapper_validate_cp_model(model_buf.as_ptr(), model_buf.len()) };
let res = unsafe { CStr::from_ptr(char_ptr) }
.to_str()
.unwrap()
.to_owned();
unsafe { libc::free(char_ptr as _) };
res
}
/// Verifies that the given variable assignment is a feasible solution
/// of the given model. The values vector should be in one to one
/// correspondence with the model.variables() list of variables.
///
/// # Example
///
/// ```
/// # use cp_sat::builder::CpModelBuilder;
/// # use cp_sat::proto::CpSolverStatus;
/// # use cp_sat::ffi::solution_is_feasible;
/// let mut model = CpModelBuilder::default();
/// let x = model.new_bool_var();
/// let y = model.new_bool_var();
/// model.add_and([x, y]);
/// assert!(solution_is_feasible(model.proto(), &[1, 1]));
/// assert!(!solution_is_feasible(model.proto(), &[1, 0]));
/// assert!(!solution_is_feasible(model.proto(), &[0, 1]));
/// assert!(!solution_is_feasible(model.proto(), &[0, 0]));
/// ```
pub fn solution_is_feasible(model: &proto::CpModelProto, solution: &[i64]) -> bool {
let mut model_buf = Vec::default();
model.encode(&mut model_buf).unwrap();
unsafe {
cp_sat_wrapper_solution_is_feasible(
model_buf.as_ptr(),
model_buf.len(),
solution.as_ptr(),
solution.len(),
)
}
}
+2
View File
@@ -57,3 +57,5 @@ pub mod proto {
/// Interface with the CP SAT functions.
pub mod ffi;
pub use prost;