#![doc(html_root_url = "https://docs.rs/clingo/0.8.0")]
#![doc = include_str!("../README.md")]
#![allow(non_upper_case_globals)]
#![allow(clippy::try_err)]
use bitflags::bitflags;
use clingo_sys::*;
use std::cmp::Ordering;
use std::collections::HashSet;
use std::convert::Infallible;
use std::convert::TryInto;
use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::NulError;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::os::raw::c_char;
use std::os::raw::c_void;
use std::ptr::NonNull;
use std::str::Utf8Error;
use std::time::Duration;
use thiserror::Error;
pub mod ast;
mod ast_internals;
pub mod theory;
#[derive(Error, Debug)]
pub enum ClingoError {
#[error("NulError: ")]
NulError(#[from] NulError),
#[error("Utf8Error: ")]
Utf8Error(#[from] Utf8Error),
#[error("FFIError: {msg}")]
FFIError { msg: &'static str },
#[error("InternalError: {msg}, code: {code:?}, last: {last}")]
InternalError {
msg: &'static str,
code: ErrorCode,
last: &'static str,
},
#[error("ExternalError: ")]
ExternalError(#[from] ExternalError),
}
impl ClingoError {
fn new_internal(msg: &'static str) -> ClingoError {
ClingoError::InternalError {
msg,
code: error_code(),
last: error_message(),
}
}
fn new_external(msg: &'static str) -> ClingoError {
ExternalError { msg }.into()
}
}
#[derive(Error, Debug)]
#[error("ExternalError: {msg}")]
pub struct ExternalError {
pub msg: &'static str,
}
#[derive(Debug, Copy, Clone)]
pub enum ErrorType {
Success = clingo_error_e_clingo_error_success as isize,
Runtime = clingo_error_e_clingo_error_runtime as isize,
Logic = clingo_error_e_clingo_error_logic as isize,
BadAlloc = clingo_error_e_clingo_error_bad_alloc as isize,
Unknown = clingo_error_e_clingo_error_unknown as isize,
}
#[derive(Debug, Copy, Clone)]
pub enum ErrorCode {
Success,
Runtime,
Logic,
BadAlloc,
Unknown,
FFIError,
}
impl From<i32> for ErrorCode {
fn from(error: i32) -> Self {
match error as u32 {
clingo_error_e_clingo_error_success => ErrorCode::Success,
clingo_error_e_clingo_error_runtime => ErrorCode::Runtime,
clingo_error_e_clingo_error_logic => ErrorCode::Logic,
clingo_error_e_clingo_error_bad_alloc => ErrorCode::BadAlloc,
clingo_error_e_clingo_error_unknown => ErrorCode::Unknown,
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_error {}",
file!(),
line!(),
column!(),
x
);
ErrorCode::FFIError
}
}
}
}
fn error_code() -> ErrorCode {
ErrorCode::from(unsafe { clingo_error_code() })
}
fn error_message() -> &'static str {
let char_ptr: *const c_char = unsafe { clingo_error_message() };
if char_ptr.is_null() {
"Ooops, original error message is null."
} else {
let c_str = unsafe { CStr::from_ptr(char_ptr) };
c_str
.to_str()
.unwrap_or("Ooops, original error message was no valid utf8 string.")
}
}
pub fn set_error(code: ErrorType, message: &str) -> Result<(), NulError> {
let message = CString::new(message)?;
unsafe { clingo_set_error(code as clingo_error_t, message.as_ptr()) }
Ok(())
}
fn set_internal_error(code: ErrorType, message: &'static str) {
let message = CString::new(message).unwrap();
unsafe { clingo_set_error(code as clingo_error_t, message.as_ptr()) }
}
pub struct Options(clingo_options_t);
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TruthValue {
Free = clingo_truth_value_e_clingo_truth_value_free as isize,
True = clingo_truth_value_e_clingo_truth_value_true as isize,
False = clingo_truth_value_e_clingo_truth_value_false as isize,
}
impl TruthValue {
fn try_from(code: u32) -> Result<TruthValue, ClingoError> {
match code {
clingo_truth_value_e_clingo_truth_value_false => Ok(TruthValue::False),
clingo_truth_value_e_clingo_truth_value_true => Ok(TruthValue::True),
clingo_truth_value_e_clingo_truth_value_free => Ok(TruthValue::Free),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_truth_value {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_truth_value.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum ClauseType {
Learnt = clingo_clause_type_e_clingo_clause_type_learnt as isize,
Static = clingo_clause_type_e_clingo_clause_type_static as isize,
Volatile = clingo_clause_type_e_clingo_clause_type_volatile as isize,
VolatileStatic = clingo_clause_type_e_clingo_clause_type_volatile_static as isize,
}
#[derive(Debug)]
enum SolveEventType {
Model = clingo_solve_event_type_e_clingo_solve_event_type_model as isize,
Unsat = clingo_solve_event_type_e_clingo_solve_event_type_unsat as isize,
Statistics = clingo_solve_event_type_e_clingo_solve_event_type_statistics as isize,
Finish = clingo_solve_event_type_e_clingo_solve_event_type_finish as isize,
}
impl SolveEventType {
fn try_from(code: u32) -> Result<SolveEventType, ClingoError> {
match code {
clingo_solve_event_type_e_clingo_solve_event_type_model => Ok(SolveEventType::Model),
clingo_solve_event_type_e_clingo_solve_event_type_unsat => Ok(SolveEventType::Unsat),
clingo_solve_event_type_e_clingo_solve_event_type_statistics => {
Ok(SolveEventType::Statistics)
}
clingo_solve_event_type_e_clingo_solve_event_type_finish => Ok(SolveEventType::Finish),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_solve_event_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_solve_event_type.",
})
}
}
}
}
#[derive(Debug)]
pub enum SolveEvent<'a> {
Model(&'a mut Model),
Unsat,
Statistics {
step: &'a mut Statistics,
akku: &'a mut Statistics,
},
Finish(&'a mut SolveResult),
}
#[derive(Debug, Copy, Clone)]
pub enum StatisticsType {
Empty = clingo_statistics_type_e_clingo_statistics_type_empty as isize,
Value = clingo_statistics_type_e_clingo_statistics_type_value as isize,
Array = clingo_statistics_type_e_clingo_statistics_type_array as isize,
Map = clingo_statistics_type_e_clingo_statistics_type_map as isize,
}
impl StatisticsType {
fn try_from(code: u32) -> Result<StatisticsType, ClingoError> {
match code {
clingo_statistics_type_e_clingo_statistics_type_empty => Ok(StatisticsType::Empty),
clingo_statistics_type_e_clingo_statistics_type_value => Ok(StatisticsType::Value),
clingo_statistics_type_e_clingo_statistics_type_array => Ok(StatisticsType::Array),
clingo_statistics_type_e_clingo_statistics_type_map => Ok(StatisticsType::Map),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_statistics_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_statistics_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum SymbolType {
Infimum = clingo_symbol_type_e_clingo_symbol_type_infimum as isize,
Number = clingo_symbol_type_e_clingo_symbol_type_number as isize,
String = clingo_symbol_type_e_clingo_symbol_type_string as isize,
Function = clingo_symbol_type_e_clingo_symbol_type_function as isize,
Supremum = clingo_symbol_type_e_clingo_symbol_type_supremum as isize,
}
impl SymbolType {
fn try_from(code: u32) -> Result<SymbolType, ClingoError> {
match code {
clingo_symbol_type_e_clingo_symbol_type_infimum => Ok(SymbolType::Infimum),
clingo_symbol_type_e_clingo_symbol_type_number => Ok(SymbolType::Number),
clingo_symbol_type_e_clingo_symbol_type_string => Ok(SymbolType::String),
clingo_symbol_type_e_clingo_symbol_type_function => Ok(SymbolType::Function),
clingo_symbol_type_e_clingo_symbol_type_supremum => Ok(SymbolType::Supremum),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_symbol_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_symbol_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum Warning {
OperationUndefined = clingo_warning_e_clingo_warning_operation_undefined as isize,
RuntimeError = clingo_warning_e_clingo_warning_runtime_error as isize,
AtomUndefined = clingo_warning_e_clingo_warning_atom_undefined as isize,
FileIncluded = clingo_warning_e_clingo_warning_file_included as isize,
VariableUnbound = clingo_warning_e_clingo_warning_variable_unbounded as isize,
GlobalVariable = clingo_warning_e_clingo_warning_global_variable as isize,
Other = clingo_warning_e_clingo_warning_other as isize,
}
impl Warning {
fn try_from(code: u32) -> Result<Warning, ClingoError> {
match code {
clingo_warning_e_clingo_warning_atom_undefined => Ok(Warning::AtomUndefined),
clingo_warning_e_clingo_warning_file_included => Ok(Warning::FileIncluded),
clingo_warning_e_clingo_warning_global_variable => Ok(Warning::GlobalVariable),
clingo_warning_e_clingo_warning_operation_undefined => Ok(Warning::OperationUndefined),
clingo_warning_e_clingo_warning_other => Ok(Warning::Other),
clingo_warning_e_clingo_warning_runtime_error => Ok(Warning::RuntimeError),
clingo_warning_e_clingo_warning_variable_unbounded => Ok(Warning::VariableUnbound),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_warning {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_warning.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum ExternalType {
Free = clingo_external_type_e_clingo_external_type_free as isize,
True = clingo_external_type_e_clingo_external_type_true as isize,
False = clingo_external_type_e_clingo_external_type_false as isize,
Release = clingo_external_type_e_clingo_external_type_release as isize,
}
impl ExternalType {
fn try_from(code: u32) -> Result<ExternalType, ClingoError> {
match code {
clingo_external_type_e_clingo_external_type_false => Ok(ExternalType::False),
clingo_external_type_e_clingo_external_type_free => Ok(ExternalType::Free),
clingo_external_type_e_clingo_external_type_release => Ok(ExternalType::Release),
clingo_external_type_e_clingo_external_type_true => Ok(ExternalType::True),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_external_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_external_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum HeuristicType {
Level = clingo_heuristic_type_e_clingo_heuristic_type_level as isize,
Sign = clingo_heuristic_type_e_clingo_heuristic_type_sign as isize,
Factor = clingo_heuristic_type_e_clingo_heuristic_type_factor as isize,
Init = clingo_heuristic_type_e_clingo_heuristic_type_init as isize,
True = clingo_heuristic_type_e_clingo_heuristic_type_true as isize,
False = clingo_heuristic_type_e_clingo_heuristic_type_false as isize,
}
impl HeuristicType {
fn try_from(code: u32) -> Result<HeuristicType, ClingoError> {
match code {
clingo_heuristic_type_e_clingo_heuristic_type_factor => Ok(HeuristicType::Factor),
clingo_heuristic_type_e_clingo_heuristic_type_false => Ok(HeuristicType::False),
clingo_heuristic_type_e_clingo_heuristic_type_init => Ok(HeuristicType::Init),
clingo_heuristic_type_e_clingo_heuristic_type_level => Ok(HeuristicType::Level),
clingo_heuristic_type_e_clingo_heuristic_type_sign => Ok(HeuristicType::Sign),
clingo_heuristic_type_e_clingo_heuristic_type_true => Ok(HeuristicType::True),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_heuristic_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_heuristic_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum TheoryTermType {
Tuple = clingo_theory_term_type_e_clingo_theory_term_type_tuple as isize,
List = clingo_theory_term_type_e_clingo_theory_term_type_list as isize,
Set = clingo_theory_term_type_e_clingo_theory_term_type_set as isize,
Function = clingo_theory_term_type_e_clingo_theory_term_type_function as isize,
Number = clingo_theory_term_type_e_clingo_theory_term_type_number as isize,
Symbol = clingo_theory_term_type_e_clingo_theory_term_type_symbol as isize,
}
impl TheoryTermType {
fn try_from(code: u32) -> Result<TheoryTermType, ClingoError> {
match code {
clingo_theory_term_type_e_clingo_theory_term_type_tuple => Ok(TheoryTermType::Tuple),
clingo_theory_term_type_e_clingo_theory_term_type_list => Ok(TheoryTermType::List),
clingo_theory_term_type_e_clingo_theory_term_type_set => Ok(TheoryTermType::Set),
clingo_theory_term_type_e_clingo_theory_term_type_function => {
Ok(TheoryTermType::Function)
}
clingo_theory_term_type_e_clingo_theory_term_type_number => Ok(TheoryTermType::Number),
clingo_theory_term_type_e_clingo_theory_term_type_symbol => Ok(TheoryTermType::Symbol),
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_theory_term_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_theory_term_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum ModelType {
StableModel = clingo_model_type_e_clingo_model_type_stable_model as isize,
BraveConsequences = clingo_model_type_e_clingo_model_type_brave_consequences as isize,
CautiousConsequences = clingo_model_type_e_clingo_model_type_cautious_consequences as isize,
}
impl ModelType {
fn try_from(code: u32) -> Result<ModelType, ClingoError> {
match code {
clingo_model_type_e_clingo_model_type_stable_model => Ok(ModelType::StableModel),
clingo_model_type_e_clingo_model_type_brave_consequences => {
Ok(ModelType::BraveConsequences)
}
clingo_model_type_e_clingo_model_type_cautious_consequences => {
Ok(ModelType::CautiousConsequences)
}
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_model_type {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_model_type.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum PropagatorCheckMode {
None = clingo_propagator_check_mode_e_clingo_propagator_check_mode_none as isize,
Total = clingo_propagator_check_mode_e_clingo_propagator_check_mode_total as isize,
Fixpoint = clingo_propagator_check_mode_e_clingo_propagator_check_mode_fixpoint as isize,
Both = clingo_propagator_check_mode_e_clingo_propagator_check_mode_both as isize,
}
impl PropagatorCheckMode {
fn try_from(code: u32) -> Result<PropagatorCheckMode, ClingoError> {
match code {
clingo_propagator_check_mode_e_clingo_propagator_check_mode_fixpoint => {
Ok(PropagatorCheckMode::Fixpoint)
}
clingo_propagator_check_mode_e_clingo_propagator_check_mode_total => {
Ok(PropagatorCheckMode::Total)
}
clingo_propagator_check_mode_e_clingo_propagator_check_mode_none => {
Ok(PropagatorCheckMode::None)
}
x => {
eprintln!(
"FFIError in {} {}, {} : Failed to match clingo_propagator_check_mode {}",
file!(),
line!(),
column!(),
x
);
Err(ClingoError::FFIError {
msg: "Failed to match clingo_propagator_check_mode.",
})
}
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum WeigthConstraintType {
ImplicationLeft =
clingo_weight_constraint_type_e_clingo_weight_constraint_type_implication_left as isize,
ImplicationRight =
clingo_weight_constraint_type_e_clingo_weight_constraint_type_implication_right as isize,
Equivalence =
clingo_weight_constraint_type_e_clingo_weight_constraint_type_equivalence as isize,
}
bitflags! {
pub struct ConfigurationType: u32 {
const VALUE =
clingo_configuration_type_e_clingo_configuration_type_value;
const ARRAY =
clingo_configuration_type_e_clingo_configuration_type_array;
const MAP =
clingo_configuration_type_e_clingo_configuration_type_map;
}
}
bitflags! {
pub struct SolveMode: u32 {
const ASYNC = clingo_solve_mode_e_clingo_solve_mode_async;
const YIELD = clingo_solve_mode_e_clingo_solve_mode_yield;
}
}
bitflags! {
pub struct ShowType: u32 {
const THEORY = clingo_show_type_e_clingo_show_type_theory;
const SHOWN = clingo_show_type_e_clingo_show_type_shown;
const ATOMS = clingo_show_type_e_clingo_show_type_atoms;
const TERMS = clingo_show_type_e_clingo_show_type_terms;
const ALL = clingo_show_type_e_clingo_show_type_all;
const COMPLEMENT = clingo_show_type_e_clingo_show_type_complement;
}
}
bitflags! {
#[derive(Debug)]
pub struct SolveResult: u32 {
const SATISFIABLE = clingo_solve_result_e_clingo_solve_result_satisfiable;
const UNSATISFIABLE =
clingo_solve_result_e_clingo_solve_result_unsatisfiable;
const EXHAUSTED = clingo_solve_result_e_clingo_solve_result_exhausted;
const INTERRUPTED = clingo_solve_result_e_clingo_solve_result_interrupted;
}
}
type SolveEventCallback = unsafe extern "C" fn(
type_: clingo_solve_event_type_t,
event: *mut c_void,
event_handler: *mut c_void,
goon: *mut bool,
) -> bool;
pub trait SolveEventHandler {
fn on_solve_event(&mut self, _event: SolveEvent, _goon: &mut bool) -> bool {
true
}
}
unsafe extern "C" fn unsafe_solve_callback<T: SolveEventHandler>(
event_type: clingo_solve_event_type_t,
event_data: *mut c_void,
event_handler: *mut c_void,
goon: *mut bool,
) -> bool {
if event_handler.is_null() | goon.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_solve_callback() got a null pointer.",
);
return false;
}
let event_handler = &mut *(event_handler as *mut T);
let goon = &mut *goon;
match SolveEventType::try_from(event_type) {
Ok(SolveEventType::Model) => {
let model = &mut *(event_data as *mut Model);
let event = SolveEvent::Model(model);
event_handler.on_solve_event(event, goon)
}
Ok(SolveEventType::Unsat) => {
let event = SolveEvent::Unsat;
event_handler.on_solve_event(event, goon)
}
Ok(SolveEventType::Statistics) => {
if event_data.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_solve_callback() got a null pointer event_data.",
);
return false;
}
let stats: &mut [&mut Statistics] =
std::slice::from_raw_parts_mut(event_data as *mut &mut Statistics, 2);
let stats: &mut [&mut Statistics; 2] =
stats.try_into().expect("slice has more than two items");
let stats = stats.split_at_mut(1);
let event = SolveEvent::Statistics {
step: stats.0[0],
akku: stats.1[0],
};
event_handler.on_solve_event(event, goon)
}
Ok(SolveEventType::Finish) => {
if event_data.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_solve_callback() got a null pointer event_data.",
);
return false;
}
let solve_result = &mut *(event_data as *mut SolveResult);
let event = SolveEvent::Finish(solve_result);
event_handler.on_solve_event(event, goon)
}
Err(e) => {
eprintln!("{}", e);
set_internal_error(
ErrorType::Runtime,
"Error in unsafe_solve_callback(): unknown event_type.",
);
false
}
}
}
type LoggingCallback =
unsafe extern "C" fn(code: clingo_warning_t, message: *const c_char, logger: *mut c_void);
pub trait Logger {
fn log(&mut self, code: Warning, message: &str) {
eprintln!("warn {:?}: {}", code, message);
}
}
unsafe extern "C" fn unsafe_logging_callback<L: Logger>(
code: clingo_warning_t,
message: *const c_char,
logger: *mut c_void,
) {
if message.is_null() | logger.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_logging_callback() got a null pointer.",
);
return;
}
let message = CStr::from_ptr(message);
let logger = &mut *(logger as *mut L);
if let Err(e) = try_logging_callback(logger, code, message) {
eprintln!("Error in unsafe_logging_callback(): {}.", e);
set_internal_error(ErrorType::Runtime, "Error in unsafe_logging_callback().");
}
}
fn try_logging_callback<L: Logger>(
logger: &mut L,
code: clingo_warning_t,
message: &CStr,
) -> Result<(), ClingoError> {
let code = Warning::try_from(code as u32)?;
let message = message.to_str()?;
logger.log(code, message);
Ok(())
}
type GroundCallback = unsafe extern "C" fn(
location: *const clingo_location_t,
name: *const c_char,
arguments: *const clingo_symbol_t,
arguments_size: usize,
event_handler: *mut c_void,
symbol_callback: clingo_symbol_callback_t,
symbol_callback_data: *mut c_void,
) -> bool;
pub trait FunctionHandler {
fn on_external_function(
&mut self,
location: &ast::Location,
name: &str,
arguments: &[Symbol],
) -> Result<Vec<Symbol>, ExternalError>;
}
unsafe extern "C" fn unsafe_ground_callback<T: FunctionHandler>(
location: *const clingo_location_t,
name: *const c_char,
arguments: *const clingo_symbol_t,
arguments_size: usize,
event_handler: *mut c_void,
symbol_callback: clingo_symbol_callback_t,
symbol_callback_data: *mut c_void,
) -> bool {
if location.is_null()
| name.is_null()
| (arguments_size > 0 && arguments.is_null())
| event_handler.is_null()
{
set_internal_error(
ErrorType::Runtime,
"unsafe_ground_callback() got a null pointer.",
);
return false;
}
let location = &*(location as *const ast::Location);
let name = CStr::from_ptr(name);
let arguments = std::slice::from_raw_parts(arguments as *const Symbol, arguments_size);
let event_handler = &mut *(event_handler as *mut T);
match try_symbol_callback(
event_handler,
location,
name,
arguments,
symbol_callback,
symbol_callback_data,
) {
Ok(x) => x,
Err(e) => {
eprintln!("Error in unsafe_ground_callback(): {}.", e);
set_internal_error(ErrorType::Runtime, "Error in unsafe_ground_callback().");
false
}
}
}
unsafe fn try_symbol_callback(
efh: &mut dyn FunctionHandler,
location: &ast::Location,
name: &CStr,
arguments: &[Symbol],
symbol_callback: clingo_symbol_callback_t,
symbol_callback_data: *mut c_void,
) -> Result<bool, ClingoError> {
let name = name.to_str()?;
let symbols = efh.on_external_function(location, name, arguments)?;
if let Some(symbol_callback) = symbol_callback {
let v: Vec<clingo_symbol_t> = symbols.iter().map(|symbol| symbol.0).collect();
Ok(symbol_callback(
v.as_slice().as_ptr(),
v.len(),
symbol_callback_data,
))
} else {
Ok(true)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct SolverLiteral(clingo_literal_t);
impl SolverLiteral {
pub fn negate(self) -> SolverLiteral {
SolverLiteral(-(self.0))
}
pub fn get_integer(self) -> i32 {
self.0
}
}
impl From<Atom> for SolverLiteral {
fn from(atom: Atom) -> Self {
SolverLiteral(atom.0 as i32)
}
}
#[derive(Debug, Copy, Clone)]
pub struct Atom(clingo_atom_t);
impl From<SolverLiteral> for Atom {
fn from(literal: SolverLiteral) -> Self {
Atom(literal.0 as u32)
}
}
#[derive(Debug, Copy, Clone)]
pub struct Id(clingo_id_t);
impl Id {
pub fn get_integer(self) -> u32 {
self.0
}
}
impl fmt::Display for Id {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
#[derive(Debug, Copy, Clone)]
pub struct WeightedLiteral(clingo_weighted_literal);
impl WeightedLiteral {
pub fn literal(self) -> SolverLiteral {
SolverLiteral(self.0.literal)
}
pub fn weight(self) -> i32 {
self.0.weight
}
}
#[derive(Debug, Copy, Clone)]
pub struct Signature(clingo_signature_t);
impl PartialEq for Signature {
fn eq(&self, other: &Signature) -> bool {
unsafe { clingo_signature_is_equal_to(self.0, other.0) }
}
}
impl Eq for Signature {}
impl PartialOrd for Signature {
fn partial_cmp(&self, other: &Signature) -> Option<Ordering> {
if unsafe { clingo_signature_is_less_than(self.0, other.0) } {
return Some(Ordering::Less);
}
if unsafe { clingo_signature_is_less_than(other.0, self.0) } {
return Some(Ordering::Greater);
}
Some(Ordering::Equal)
}
}
impl Hash for Signature {
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe { clingo_signature_hash(self.0) }.hash(state);
}
}
impl Signature {
pub fn new(name: &str, arity: u32, positive: bool) -> Result<Signature, ClingoError> {
let name = CString::new(name)?;
let mut signature = 0;
if !unsafe { clingo_signature_create(name.as_ptr(), arity, positive, &mut signature) } {
return Err(ClingoError::new_internal(
"Call to clingo_signature_create() failed",
));
}
Ok(Signature(signature))
}
pub fn name(&self) -> Result<&'static str, Utf8Error> {
let char_ptr: *const c_char = unsafe { clingo_signature_name(self.0) };
if char_ptr.is_null() {
Ok("")
} else {
let c_str = unsafe { CStr::from_ptr(char_ptr) };
c_str.to_str()
}
}
pub fn arity(self) -> u32 {
unsafe { clingo_signature_arity(self.0) }
}
pub fn is_positive(self) -> bool {
unsafe { clingo_signature_is_positive(self.0) }
}
pub fn is_negative(self) -> bool {
unsafe { clingo_signature_is_negative(self.0) }
}
}
#[derive(Debug, Copy, Clone)]
pub struct Symbol(clingo_symbol_t);
impl PartialEq for Symbol {
fn eq(&self, other: &Symbol) -> bool {
unsafe { clingo_symbol_is_equal_to(self.0, other.0) }
}
}
impl Eq for Symbol {}
impl PartialOrd for Symbol {
fn partial_cmp(&self, other: &Symbol) -> Option<Ordering> {
if unsafe { clingo_symbol_is_less_than(self.0, other.0) } {
return Some(Ordering::Less);
}
if unsafe { clingo_symbol_is_less_than(other.0, self.0) } {
return Some(Ordering::Greater);
}
Some(Ordering::Equal)
}
}
impl Hash for Symbol {
fn hash<H: Hasher>(&self, state: &mut H) {
unsafe { clingo_symbol_hash(self.0) }.hash(state);
}
}
impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut size: usize = 0;
if !unsafe { clingo_symbol_to_string_size(self.0, &mut size) } {
eprintln!("Call to clingo_symbol_to_string_size() failed");
return Err(fmt::Error);
}
let mut string = Vec::with_capacity(size);
let string_ptr = string.as_mut_ptr();
if !unsafe { clingo_symbol_to_string(self.0, string_ptr, size) } {
eprintln!("Call to clingo_symbol_to_string() failed");
return Err(fmt::Error);
}
let c_str: &CStr = unsafe { CStr::from_ptr(string_ptr) };
let str_slice: &str = match c_str.to_str() {
Ok(slice) => slice,
Err(e) => {
eprintln!("{}", e);
return Err(fmt::Error);
}
};
std::fmt::Display::fmt(str_slice, f)
}
}
impl Symbol {
pub fn create_number(number: i32) -> Symbol {
let mut symbol = 0;
unsafe { clingo_symbol_create_number(number, &mut symbol) };
Symbol(symbol)
}
pub fn create_supremum() -> Symbol {
let mut symbol = 0;
unsafe { clingo_symbol_create_supremum(&mut symbol) };
Symbol(symbol)
}
pub fn create_infimum() -> Symbol {
let mut symbol = 0;
unsafe { clingo_symbol_create_infimum(&mut symbol) };
Symbol(symbol)
}
pub fn create_string(string: &str) -> Result<Symbol, ClingoError> {
let mut symbol = 0;
let c_str = CString::new(string)?;
if !unsafe { clingo_symbol_create_string(c_str.as_ptr(), &mut symbol) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_create_string() failed",
));
}
Ok(Symbol(symbol))
}
pub fn create_id(name: &str, positive: bool) -> Result<Symbol, ClingoError> {
let mut symbol = 0;
let name = CString::new(name)?;
if !unsafe { clingo_symbol_create_id(name.as_ptr(), positive, &mut symbol) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_create_id() failed",
));
}
Ok(Symbol(symbol))
}
pub fn create_function(
name: &str,
arguments: &[Symbol],
positive: bool,
) -> Result<Symbol, ClingoError> {
let mut symbol = 0;
let name = CString::new(name)?;
if !unsafe {
clingo_symbol_create_function(
name.as_ptr(),
arguments.as_ptr() as *const clingo_symbol_t,
arguments.len(),
positive,
&mut symbol,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_create_function() failed",
));
}
Ok(Symbol(symbol))
}
pub fn number(self) -> Result<i32, ClingoError> {
let mut number = 0;
if !unsafe { clingo_symbol_number(self.0, &mut number) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_number() failed",
));
}
Ok(number)
}
pub fn name(&self) -> Result<&'static str, ClingoError> {
let mut char_ptr = std::ptr::null();
if !unsafe { clingo_symbol_name(self.0, &mut char_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_name() failed",
));
}
if char_ptr.is_null() {
return Err(ClingoError::new_internal(
"clingo_symbol_name() returned a null pointer.",
));
}
let c_str = unsafe { CStr::from_ptr(char_ptr) };
Ok(c_str.to_str()?)
}
pub fn string(&self) -> Result<&'static str, ClingoError> {
let mut char_ptr = std::ptr::null();
if !unsafe { clingo_symbol_string(self.0, &mut char_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_string() failed",
));
}
if char_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_symbol_string() returned a null pointer.",
});
}
let c_str = unsafe { CStr::from_ptr(char_ptr) };
Ok(c_str.to_str()?)
}
pub fn is_positive(self) -> Result<bool, ClingoError> {
let mut positive = false;
if !unsafe { clingo_symbol_is_positive(self.0, &mut positive) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_is_positive() failed",
));
}
Ok(positive)
}
pub fn is_negative(self) -> Result<bool, ClingoError> {
let mut negative = false;
if !unsafe { clingo_symbol_is_negative(self.0, &mut negative) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_is_negative() failed",
));
}
Ok(negative)
}
pub fn arguments(self) -> Result<Vec<Symbol>, ClingoError> {
let mut symbol_ptr = std::ptr::null();
let mut size: usize = 0;
if !unsafe { clingo_symbol_arguments(self.0, &mut symbol_ptr, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbol_arguments() failed",
));
}
let mut symbols = Vec::<Symbol>::with_capacity(size);
for _ in 0..size {
if symbol_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_symbol_arguments() returned a null pointer.",
});
}
let nsymbol = unsafe { *symbol_ptr };
symbols.push(Symbol(nsymbol));
symbol_ptr = unsafe { symbol_ptr.offset(1) };
}
Ok(symbols)
}
pub fn symbol_type(self) -> Result<SymbolType, ClingoError> {
SymbolType::try_from(unsafe { clingo_symbol_type(self.0) } as u32)
}
}
pub fn version() -> (i32, i32, i32) {
let mut major = 0;
let mut minor = 0;
let mut revision = 0;
unsafe { clingo_version(&mut major, &mut minor, &mut revision) };
(major, minor, revision)
}
#[derive(Debug, Clone)]
pub struct Part {
part: clingo_part,
_params: Vec<Symbol>,
}
impl Part {
pub fn new(name: &str, params: Vec<Symbol>) -> Result<Part, ClingoError> {
let name = internalize_string(name)?;
Ok(Part {
part: clingo_part {
name: name as *const c_char,
params: params.as_ptr() as *const clingo_symbol_t,
size: params.len(),
},
_params: params,
})
}
}
pub trait Propagator {
fn init(&mut self, _init: &mut PropagateInit) -> bool {
true
}
fn propagate(&mut self, _control: &mut PropagateControl, _changes: &[SolverLiteral]) -> bool {
true
}
fn undo(&mut self, _control: &mut PropagateControl, _changes: &[SolverLiteral]) {}
fn check(&mut self, _control: &mut PropagateControl) -> bool {
true
}
fn decide(
&mut self,
_thread_id: Id,
_assignment: &Assignment,
_fallback: SolverLiteral,
_decision: &mut SolverLiteral,
) -> bool {
true
}
}
unsafe extern "C" fn unsafe_init<T: Propagator>(
init: *mut clingo_propagate_init_t,
propagator: *mut c_void,
) -> bool {
if init.is_null() | propagator.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_init() got a null pointer.");
return false;
}
let init = &mut *(init as *mut PropagateInit);
let propagator = &mut *(propagator as *mut T);
propagator.init(init)
}
unsafe extern "C" fn unsafe_propagate<T: Propagator>(
control: *mut clingo_propagate_control_t,
changes: *const clingo_literal_t,
size: usize,
propagator: *mut c_void,
) -> bool {
if control.is_null() | (size > 0 && changes.is_null()) | propagator.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_propagate() got a null pointer.");
return false;
}
let control = &mut *(control as *mut PropagateControl);
let changes = std::slice::from_raw_parts(changes as *const SolverLiteral, size);
let propagator = &mut *(propagator as *mut T);
propagator.propagate(control, changes)
}
unsafe extern "C" fn unsafe_undo<T: Propagator>(
control: *const clingo_propagate_control_t,
changes: *const clingo_literal_t,
size: usize,
propagator: *mut c_void,
) {
if control.is_null() | (size > 0 && changes.is_null()) | propagator.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_undo() got a null pointer.");
return;
}
let control = &mut *(control as *mut PropagateControl);
let changes = std::slice::from_raw_parts(changes as *const SolverLiteral, size);
let propagator = &mut *(propagator as *mut T);
propagator.undo(control, changes)
}
unsafe extern "C" fn unsafe_check<T: Propagator>(
control: *mut clingo_propagate_control_t,
propagator: *mut c_void,
) -> bool {
if control.is_null() | propagator.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_check() got a null pointer.");
return false;
}
let control = &mut *(control as *mut PropagateControl);
let propagator = &mut *(propagator as *mut T);
propagator.check(control)
}
unsafe extern "C" fn unsafe_decide<T: Propagator>(
thread_id: clingo_id_t,
assignment: *const clingo_assignment_t,
fallback: clingo_literal_t,
propagator: *mut ::std::os::raw::c_void,
decision: *mut clingo_literal_t,
) -> bool {
if assignment.is_null() | propagator.is_null() | decision.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_decide() got a null pointer.");
return false;
}
let assignment = &*(assignment as *const Assignment);
let fallback = SolverLiteral(fallback);
let propagator = &mut *(propagator as *mut T);
let decision = &mut *(decision as *mut SolverLiteral);
propagator.decide(Id(thread_id), assignment, fallback, decision)
}
pub mod defaults {
use crate::ast::Location;
use crate::{
ExternalError, FunctionHandler, GroundProgramObserver, Logger, Propagator,
SolveEventHandler, Symbol,
};
#[derive(Debug, Clone, Copy)]
pub struct Non;
impl Logger for Non {}
impl Propagator for Non {}
impl GroundProgramObserver for Non {}
impl FunctionHandler for Non {
fn on_external_function(
&mut self,
_location: &Location,
_name: &str,
_arguments: &[Symbol],
) -> Result<Vec<Symbol>, ExternalError> {
Ok(vec![])
}
}
impl SolveEventHandler for Non {}
}
pub trait ControlCtx {
type L: Logger;
type P: Propagator;
type O: GroundProgramObserver;
type F: FunctionHandler;
fn logger(&mut self) -> (&mut Self::L, u32);
fn propagator(&mut self) -> (&mut Self::P, bool);
fn observer(&mut self) -> (&mut Self::O, bool);
fn function_handler(&mut self) -> &mut Self::F;
}
#[derive(Debug)]
pub struct DefaultCtx {
non: defaults::Non,
}
impl ControlCtx for DefaultCtx {
type L = defaults::Non;
type P = defaults::Non;
type O = defaults::Non;
type F = defaults::Non;
fn logger(&mut self) -> (&mut Self::L, u32) {
(&mut self.non, 0)
}
fn propagator(&mut self) -> (&mut Self::P, bool) {
(&mut self.non, false)
}
fn observer(&mut self) -> (&mut Self::O, bool) {
(&mut self.non, false)
}
fn function_handler(&mut self) -> &mut Self::F {
&mut self.non
}
}
#[derive(Debug)]
pub struct GenericControl<C: ControlCtx> {
ctl: NonNull<clingo_control_t>,
copied: bool,
context: Box<C>,
}
pub type Control = GenericControl<DefaultCtx>;
impl<C: ControlCtx> Drop for GenericControl<C> {
fn drop(&mut self) {
if !self.copied {
unsafe { clingo_control_free(self.ctl.as_ptr()) }
}
}
}
impl<C: ControlCtx> GenericControl<C> {
pub fn ground(&mut self, parts: &[Part]) -> Result<(), ClingoError> {
let parts_size = parts.len();
let parts = parts
.iter()
.map(|arg| arg.part)
.collect::<Vec<clingo_part>>();
let function_handler = self.context.function_handler();
if !unsafe {
clingo_control_ground(
self.ctl.as_ptr(),
parts.as_ptr(),
parts_size,
Some(unsafe_ground_callback::<C::F> as GroundCallback),
function_handler as *mut C::F as *mut c_void,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_ground() failed",
));
}
Ok(())
}
pub fn register_control_context<T: ControlCtx>(mut self, context: T) -> GenericControl<T> {
let context = Box::new(context);
self.copied = true;
GenericControl {
ctl: self.ctl,
copied: false,
context,
}
}
pub fn solve(
self,
mode: SolveMode,
assumptions: &[SolverLiteral],
) -> Result<GenericSolveHandle<C, defaults::Non>, ClingoError> {
let mut handle = std::ptr::null_mut();
let event_handler = std::ptr::null_mut();
if !unsafe {
clingo_control_solve(
self.ctl.as_ptr(),
mode.bits(),
assumptions.as_ptr() as *const clingo_literal_t,
assumptions.len(),
None,
event_handler,
&mut handle,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_solve() failed",
));
}
match NonNull::new(handle) {
Some(handle) => Ok(GenericSolveHandle {
handle,
ctl: self,
_event_handler: Box::new(defaults::Non),
}),
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
pub fn solve_with_event_handler<T: SolveEventHandler>(
self,
mode: SolveMode,
assumptions: &[SolverLiteral],
event_handler: T,
) -> Result<GenericSolveHandle<C, T>, ClingoError> {
let mut handle = std::ptr::null_mut();
let mut event_handler = Box::new(event_handler);
if !unsafe {
clingo_control_solve(
self.ctl.as_ptr(),
mode.bits(),
assumptions.as_ptr() as *const clingo_literal_t,
assumptions.len(),
Some(unsafe_solve_callback::<T> as SolveEventCallback),
event_handler.as_mut() as *mut T as *mut c_void,
&mut handle,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_solve() failed",
));
}
match NonNull::new(handle) {
Some(handle) => Ok(GenericSolveHandle {
handle,
ctl: self,
_event_handler: event_handler,
}),
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
pub fn add(
&mut self,
name: &str,
parameters: &[&str],
program: &str,
) -> Result<(), ClingoError> {
let name = CString::new(name)?;
let program = CString::new(program)?;
let program_ptr = program.as_ptr();
let parameters_size = parameters.len();
let mut l_parameters = vec![];
for arg in parameters {
l_parameters.push(CString::new(*arg)?);
}
let c_parameters = l_parameters
.iter()
.map(|arg| arg.as_ptr())
.collect::<Vec<*const c_char>>();
if !unsafe {
clingo_control_add(
self.ctl.as_ptr(),
name.as_ptr(),
c_parameters.as_ptr(),
parameters_size,
program_ptr,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_add() failed",
));
}
Ok(())
}
pub fn cleanup(&mut self) -> Result<(), ClingoError> {
if !unsafe { clingo_control_cleanup(self.ctl.as_ptr()) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_cleanup() failed",
));
}
Ok(())
}
pub fn assign_external(
&mut self,
literal: SolverLiteral,
value: TruthValue,
) -> Result<(), ClingoError> {
if !unsafe {
clingo_control_assign_external(
self.ctl.as_ptr(),
literal.0,
value as clingo_truth_value_t,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_assign_external() failed",
));
}
Ok(())
}
pub fn release_external(
&mut self,
SolverLiteral(literal): SolverLiteral,
) -> Result<(), ClingoError> {
if !unsafe { clingo_control_release_external(self.ctl.as_ptr(), literal) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_release_external() failed",
));
}
Ok(())
}
fn register_propagator(&mut self) -> Result<(), ClingoError> {
let (propagator, sequential) = self.context.propagator();
let clingo_propagator = clingo_propagator_t {
init: Some(unsafe_init::<C::P>),
propagate: Some(unsafe_propagate::<C::P>),
undo: Some(unsafe_undo::<C::P>),
check: Some(unsafe_check::<C::P>),
decide: Some(unsafe_decide::<C::P>),
};
if !unsafe {
clingo_control_register_propagator(
self.ctl.as_ptr(),
&clingo_propagator,
propagator as *mut C::P as *mut c_void,
sequential,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_register_propagator() failed",
));
}
self.copied = true;
Ok(())
}
pub fn is_conflicting(&self) -> bool {
unsafe { clingo_control_is_conflicting(self.ctl.as_ptr()) }
}
pub fn statistics(&self) -> Result<&Statistics, ClingoError> {
let mut stat = std::ptr::null();
if !unsafe { clingo_control_statistics(self.ctl.as_ptr(), &mut stat) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_statistics() failed",
));
}
match unsafe { (stat as *mut Statistics).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &Statistics.",
}),
}
}
pub fn interrupt(&mut self) {
unsafe {
clingo_control_interrupt(self.ctl.as_ptr());
}
}
pub fn configuration_mut(&mut self) -> Result<&mut Configuration, ClingoError> {
let mut conf = std::ptr::null_mut();
if !unsafe { clingo_control_configuration(self.ctl.as_ptr(), &mut conf) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_configuration() failed",
));
}
match unsafe { (conf as *mut Configuration).as_mut() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &mut Configuration.",
}),
}
}
pub fn configuration(&self) -> Result<&Configuration, ClingoError> {
let mut conf = std::ptr::null_mut();
if !unsafe { clingo_control_configuration(self.ctl.as_ptr(), &mut conf) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_configuration() failed",
));
}
match unsafe { (conf as *const Configuration).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &Configuration.",
}),
}
}
pub fn set_enable_enumeration_assumption(&mut self, enable: bool) -> Result<(), ClingoError> {
if !unsafe { clingo_control_set_enable_enumeration_assumption(self.ctl.as_ptr(), enable) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_use_enumeration_assumption() failed",
));
}
Ok(())
}
pub fn get_enable_enumeration_assumption(&self) -> bool {
unsafe { clingo_control_get_enable_enumeration_assumption(self.ctl.as_ptr()) }
}
pub fn set_enable_cleanup(&mut self, enable: bool) -> bool {
unsafe { clingo_control_set_enable_cleanup(self.ctl.as_ptr(), enable) }
}
pub fn get_enable_cleanup(&self) -> bool {
unsafe { clingo_control_get_enable_cleanup(self.ctl.as_ptr()) }
}
pub fn get_const(&self, name: &str) -> Result<Symbol, ClingoError> {
let name = CString::new(name)?;
let mut symbol = 0;
if !unsafe { clingo_control_get_const(self.ctl.as_ptr(), name.as_ptr(), &mut symbol) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_get_const() failed",
));
}
Ok(Symbol(symbol))
}
pub fn has_const(&self, name: &str) -> Result<bool, ClingoError> {
let name = CString::new(name)?;
let mut exist = false;
if !unsafe { clingo_control_has_const(self.ctl.as_ptr(), name.as_ptr(), &mut exist) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_has_const() failed",
));
}
Ok(exist)
}
pub fn symbolic_atoms<'a>(&self) -> Result<&'a SymbolicAtoms, ClingoError> {
let mut atoms = std::ptr::null();
if !unsafe { clingo_control_symbolic_atoms(self.ctl.as_ptr(), &mut atoms) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_symbolic_atoms() failed",
));
}
match unsafe { (atoms as *const SymbolicAtoms).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &SymbolicAtoms.",
}),
}
}
pub fn theory_atoms(&self) -> Result<&TheoryAtoms, ClingoError> {
let mut atoms = std::ptr::null();
if !unsafe { clingo_control_theory_atoms(self.ctl.as_ptr(), &mut atoms) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_theory_atoms() failed",
));
}
match unsafe { (atoms as *const TheoryAtoms).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &TheoryAtoms.",
}),
}
}
fn register_observer(&mut self) -> Result<(), ClingoError> {
let (observer, replace) = self.context.observer();
let gpo = clingo_ground_program_observer_t {
init_program: Some(unsafe_init_program::<C::O>),
begin_step: Some(unsafe_begin_step::<C::O>),
end_step: Some(unsafe_end_step::<C::O>),
rule: Some(unsafe_rule::<C::O>),
weight_rule: Some(unsafe_weight_rule::<C::O>),
minimize: Some(unsafe_minimize::<C::O>),
project: Some(unsafe_project::<C::O>),
output_atom: Some(unsafe_output_atom::<C::O>),
output_term: Some(unsafe_output_term::<C::O>),
external: Some(unsafe_external::<C::O>),
assume: Some(unsafe_assume::<C::O>),
heuristic: Some(unsafe_heuristic::<C::O>),
acyc_edge: Some(unsafe_acyc_edge::<C::O>),
theory_term_number: Some(unsafe_theory_term_number::<C::O>),
theory_term_string: Some(unsafe_theory_term_string::<C::O>),
theory_term_compound: Some(unsafe_theory_term_compound::<C::O>),
theory_element: Some(unsafe_theory_element::<C::O>),
theory_atom: Some(unsafe_theory_atom::<C::O>),
theory_atom_with_guard: Some(unsafe_theory_atom_with_guard::<C::O>),
};
if !unsafe {
clingo_control_register_observer(
self.ctl.as_ptr(),
&gpo,
replace,
observer as *mut C::O as *mut c_void,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_register_observer() failed",
));
}
self.copied = true;
Ok(())
}
pub fn backend(&mut self) -> Result<Backend, ClingoError> {
let mut backend = std::ptr::null_mut();
if !unsafe { clingo_control_backend(self.ctl.as_ptr(), &mut backend) } {
return Err(ClingoError::new_internal(
"Call to clingo_control_backend() failed",
));
}
if !unsafe { clingo_backend_begin(backend) } {
return Err(ClingoError::new_internal(
"Call to clingo_backend_begin() failed",
));
}
match unsafe { backend.as_mut() } {
Some(backend_ref) => Ok(Backend {
theref: backend_ref,
}),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &mut clingo_backend.",
}),
}
}
pub fn add_facts(&mut self, facts: &FactBase) -> Result<(), ClingoError> {
for sym in facts.iter() {
let loc = ast::Location::default();
let symbolic_term = ast::symbolic_term(&loc, sym)?;
let atom = ast::symbolic_atom(symbolic_term)?;
let lit = ast::basic_literal_from_symbolic_atom(&loc, ast::Sign::NoSign, atom).unwrap();
let head: ast::Literal = ast::Literal::from(lit);
let fact = ast::rule(&loc, head, &[]).unwrap();
let mut builder = ast::ProgramBuilder::from(self).unwrap();
builder
.add(&fact.into())
.expect("Failed to add statement to ProgramBuilder.");
builder.end().expect("Failed to finish building a program.");
}
Ok(())
}
pub fn all_models(self) -> Result<AllModels<C, defaults::Non>, ClingoError> {
let mut handle = std::ptr::null_mut();
let event_handler = std::ptr::null_mut();
if !unsafe {
clingo_control_solve(
self.ctl.as_ptr(),
SolveMode::YIELD.bits(),
std::ptr::null() as *const clingo_literal_t,
0,
None,
event_handler,
&mut handle,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_solve() failed",
));
}
match NonNull::new(handle) {
Some(handle) => Ok(AllModels(GenericSolveHandle {
handle,
ctl: self,
_event_handler: Box::new(defaults::Non),
})),
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
pub fn optimal_models(self) -> Result<OptimalModels<C, defaults::Non>, ClingoError> {
let mut handle = std::ptr::null_mut();
let event_handler = std::ptr::null_mut();
if !unsafe {
clingo_control_solve(
self.ctl.as_ptr(),
SolveMode::YIELD.bits(),
std::ptr::null() as *const clingo_literal_t,
0,
None,
event_handler,
&mut handle,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_solve() failed",
));
}
match NonNull::new(handle) {
Some(handle) => Ok(OptimalModels(GenericSolveHandle {
handle,
ctl: self,
_event_handler: Box::new(defaults::Non),
})),
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
}
pub fn control(arguments: std::vec::Vec<String>) -> Result<Control, ClingoError> {
let logger = None;
let logger_data = std::ptr::null_mut();
let mut args = vec![];
for arg in arguments {
args.push(CString::new(arg)?);
}
let c_args = args
.iter()
.map(|arg| arg.as_ptr())
.collect::<Vec<*const c_char>>();
let mut ctl_ptr = std::ptr::null_mut();
if !unsafe {
clingo_control_new(
c_args.as_ptr(),
c_args.len(),
logger,
logger_data,
0,
&mut ctl_ptr,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_new() failed",
));
}
match NonNull::new(ctl_ptr) {
Some(ctl) => Ok(GenericControl {
ctl,
copied: false,
context: Box::new(DefaultCtx { non: defaults::Non }),
}),
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
pub fn control_with_context<C: ControlCtx>(
arguments: Vec<String>,
mut context: C,
) -> Result<GenericControl<C>, ClingoError> {
let mut args = vec![];
for arg in arguments {
args.push(CString::new(arg)?);
}
let c_args = args
.iter()
.map(|arg| arg.as_ptr())
.collect::<Vec<*const c_char>>();
let mut ctl_ptr = std::ptr::null_mut();
let (logger, message_limit) = context.logger();
if !unsafe {
clingo_control_new(
c_args.as_ptr(),
c_args.len(),
Some(unsafe_logging_callback::<C::L> as LoggingCallback),
logger as *mut C::L as *mut c_void,
message_limit,
&mut ctl_ptr,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_control_new() failed",
));
}
match NonNull::new(ctl_ptr) {
Some(ctl) => {
let mut control = GenericControl {
ctl,
copied: false,
context: Box::new(context),
};
control.register_observer()?;
control.register_propagator()?;
Ok(control)
}
None => Err(ClingoError::FFIError {
msg: "Tried creating NonNull from a null pointer.",
})?,
}
}
#[derive(Debug)]
pub struct Configuration(clingo_configuration_t);
impl Configuration {
pub fn root(&self) -> Result<Id, ClingoError> {
let mut root_key = 0;
if !unsafe { clingo_configuration_root(&self.0, &mut root_key) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_root() failed",
));
}
Ok(Id(root_key))
}
pub fn configuration_type(&self, Id(key): Id) -> Result<ConfigurationType, ClingoError> {
let mut ctype = 0;
if !unsafe { clingo_configuration_type(&self.0, key, &mut ctype) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_type() failed",
));
}
match ConfigurationType::from_bits(ctype) {
Some(x) => Ok(x),
None => {
eprintln!(
"Failed to match to clingo_configuration_type_bitset_t {}.",
ctype
);
Err(ClingoError::FFIError {
msg: "Failed to match to clingo_configuration_type_bitset_t.",
})
}
}
}
pub fn description(&self, Id(key): Id) -> Result<&str, ClingoError> {
let mut description_ptr = std::ptr::null();
if !unsafe { clingo_configuration_description(&self.0, key, &mut description_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_description() failed",
));
}
if description_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_configuration_description() returned a null pointer.",
});
}
let cstr = unsafe { CStr::from_ptr(description_ptr) };
Ok(cstr.to_str()?)
}
pub fn array_size(&self, Id(key): Id) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_configuration_array_size(&self.0, key, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_array_size() failed",
));
}
Ok(size)
}
pub fn array_at(&self, Id(key): Id, offset: usize) -> Result<Id, ClingoError> {
let mut nkey = 0;
if !unsafe { clingo_configuration_array_at(&self.0, key, offset, &mut nkey) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_array_at() failed",
));
}
Ok(Id(nkey))
}
pub fn map_size(&self, Id(key): Id) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_configuration_map_size(&self.0, key, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_map_size() failed",
));
}
Ok(size)
}
pub fn map_has_subkey(&self, Id(key): Id, name: &str) -> Result<bool, ClingoError> {
let mut result = false;
let name = CString::new(name)?;
if !unsafe { clingo_configuration_map_has_subkey(&self.0, key, name.as_ptr(), &mut result) }
{
return Err(ClingoError::new_internal(
"Call to clingo_configuration_map_has_subkey() failed",
));
}
Ok(result)
}
pub fn map_subkey_name(&self, Id(key): Id, offset: usize) -> Result<&str, ClingoError> {
let mut name_ptr = std::ptr::null();
if !unsafe { clingo_configuration_map_subkey_name(&self.0, key, offset, &mut name_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_map_subkey_name() failed",
));
}
if name_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_configuration_map_subkey_name() returned a null pointer.",
});
}
let cstr = unsafe { CStr::from_ptr(name_ptr) };
Ok(cstr.to_str()?)
}
pub fn map_at(&self, Id(key): Id, name: &str) -> Result<Id, ClingoError> {
let mut nkey = 0;
let name = CString::new(name)?;
if !unsafe { clingo_configuration_map_at(&self.0, key, name.as_ptr(), &mut nkey) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_value_is_assigned() failed",
));
}
Ok(Id(nkey))
}
pub fn value_is_assigned(&self, Id(key): Id) -> Result<bool, ClingoError> {
let mut assigned = false;
if !unsafe { clingo_configuration_value_is_assigned(&self.0, key, &mut assigned) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_value_is_assigned() failed",
));
}
Ok(assigned)
}
pub fn value_get(&self, Id(key): Id) -> Result<String, ClingoError> {
let mut size = 0;
if !unsafe { clingo_configuration_value_get_size(&self.0, key, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_value_get_size() failed",
));
}
let mut string = Vec::with_capacity(size);
let string_ptr = string.as_mut_ptr();
if !unsafe { clingo_configuration_value_get(&self.0, key, string_ptr, size) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_value_get() failed",
));
}
let c_str: &CStr = unsafe { CStr::from_ptr(string_ptr) };
let str_slice: &str = c_str.to_str()?;
Ok(str_slice.to_owned())
}
pub fn value_set(&mut self, Id(key): Id, value: &str) -> Result<(), ClingoError> {
let value = CString::new(value)?;
if !unsafe { clingo_configuration_value_set(&mut self.0, key, value.as_ptr()) } {
return Err(ClingoError::new_internal(
"Call to clingo_configuration_value_set() failed",
));
}
Ok(())
}
}
#[derive(Debug)]
pub struct Backend<'a> {
theref: &'a mut clingo_backend_t,
}
impl<'a> Drop for Backend<'a> {
fn drop(&mut self) {
if !unsafe { clingo_backend_end(self.theref) } {
panic!("Call to clingo_backend_end() failed");
}
}
}
impl<'a> Backend<'a> {
pub fn rule(
&mut self,
choice: bool,
head: &[Atom],
body: &[SolverLiteral],
) -> Result<(), ClingoError> {
if !unsafe {
clingo_backend_rule(
self.theref,
choice,
head.as_ptr() as *const clingo_atom_t,
head.len(),
body.as_ptr() as *const clingo_literal_t,
body.len(),
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_rule() failed",
));
}
Ok(())
}
pub fn weight_rule(
&mut self,
choice: bool,
head: &[Atom],
lower_bound: i32,
body: &[WeightedLiteral],
) -> Result<(), ClingoError> {
if !unsafe {
clingo_backend_weight_rule(
self.theref,
choice,
head.as_ptr() as *const clingo_atom_t,
head.len(),
lower_bound,
body.as_ptr() as *const clingo_weighted_literal_t,
body.len(),
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_weight_rule() failed",
));
}
Ok(())
}
pub fn minimize(
&mut self,
priority: i32,
literals: &[WeightedLiteral],
) -> Result<(), ClingoError> {
if !unsafe {
clingo_backend_minimize(
self.theref,
priority,
literals.as_ptr() as *const clingo_weighted_literal_t,
literals.len(),
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_minimize() failed",
));
}
Ok(())
}
pub fn project(&mut self, atoms: &[Atom]) -> Result<(), ClingoError> {
if !unsafe {
clingo_backend_project(
self.theref,
atoms.as_ptr() as *const clingo_atom_t,
atoms.len(),
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_project() failed",
));
}
Ok(())
}
pub fn external(&mut self, atom: Atom, type_: ExternalType) -> Result<(), ClingoError> {
if !unsafe { clingo_backend_external(self.theref, atom.0, type_ as clingo_external_type_t) }
{
return Err(ClingoError::new_internal(
"Call to clingo_backend_external() failed",
));
}
Ok(())
}
pub fn assume(&mut self, literals: &[SolverLiteral]) -> Result<(), ClingoError> {
let size = literals.len();
if !unsafe {
clingo_backend_assume(
self.theref,
literals.as_ptr() as *const clingo_literal_t,
size,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_assume() failed",
));
}
Ok(())
}
pub fn heuristic(
&mut self,
atom: Atom,
htype: HeuristicType,
bias: i32,
priority: u32,
condition: &[SolverLiteral],
) -> Result<(), ClingoError> {
let size = condition.len();
if !unsafe {
clingo_backend_heuristic(
self.theref,
atom.0,
htype as clingo_heuristic_type_t,
bias,
priority,
condition.as_ptr() as *const clingo_literal_t,
size,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_heuristic() failed",
));
}
Ok(())
}
pub fn acyc_edge(
&mut self,
node_u: i32,
node_v: i32,
condition: &[SolverLiteral],
) -> Result<(), ClingoError> {
let size = condition.len();
if !unsafe {
clingo_backend_acyc_edge(
self.theref,
node_u,
node_v,
condition.as_ptr() as *const clingo_literal_t,
size,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_backend_acyc_edge() failed",
));
}
Ok(())
}
pub fn add_atom(&mut self, symbol: Option<Symbol>) -> Result<Atom, ClingoError> {
match symbol {
Some(Symbol(mut symbol)) => {
let mut atom = 0;
if unsafe { clingo_backend_add_atom(self.theref, &mut symbol, &mut atom) } {
Ok(Atom(atom))
} else {
Err(ClingoError::new_internal(
"Call to clingo_backend_add_atom() failed",
))
}
}
None => {
let mut atom = 0;
let null = std::ptr::null_mut();
if unsafe { clingo_backend_add_atom(self.theref, null, &mut atom) } {
Ok(Atom(atom))
} else {
Err(ClingoError::new_internal(
"Call to clingo_backend_add_atom() failed",
))
}
}
}
}
}
#[derive(Debug)]
pub struct Statistics(clingo_statistics_t);
impl Statistics {
pub fn root(&self) -> Result<u64, ClingoError> {
let mut root_key = 0;
if !unsafe { clingo_statistics_root(&self.0, &mut root_key) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_root() failed",
));
}
Ok(root_key)
}
pub fn statistics_type(&self, key: u64) -> Result<StatisticsType, ClingoError> {
let mut stype = 0;
if !unsafe { clingo_statistics_type(&self.0, key, &mut stype) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_type() failed",
));
}
StatisticsType::try_from(stype as u32)
}
pub fn array_size(&self, key: u64) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_statistics_array_size(&self.0, key, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_array_size() failed",
));
}
Ok(size)
}
pub fn array_at(&self, key: u64, offset: usize) -> Result<u64, ClingoError> {
let mut subkey = 0;
if !unsafe { clingo_statistics_array_at(&self.0, key, offset, &mut subkey) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_array_at() failed",
));
}
Ok(subkey)
}
pub fn array_push(&mut self, key: u64, stype: StatisticsType) -> Result<u64, ClingoError> {
let mut subkey = 0;
if !unsafe {
clingo_statistics_array_push(
&mut self.0,
key,
stype as clingo_statistics_type_t,
&mut subkey,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_array_push() failed",
));
}
Ok(subkey)
}
pub fn map_size(&self, key: u64) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_statistics_map_size(&self.0, key, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_map_size() failed",
));
}
Ok(size)
}
pub fn map_has_subkey(&self, key: u64, name: &str) -> Result<bool, ClingoError> {
let mut result = false;
let name = CString::new(name)?;
if !unsafe { clingo_statistics_map_has_subkey(&self.0, key, name.as_ptr(), &mut result) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_map_has_subkey() failed",
));
}
Ok(result)
}
pub fn map_subkey_name(&self, key: u64, offset: usize) -> Result<&str, ClingoError> {
let mut name = std::ptr::null();
if !unsafe { clingo_statistics_map_subkey_name(&self.0, key, offset, &mut name) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_map_subkey_name() failed",
));
}
if name.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_statistics_map_subkey_name() returned a null pointer.",
});
}
Ok(unsafe { CStr::from_ptr(name) }.to_str()?)
}
pub fn map_at(&self, key: u64, name: &str) -> Result<u64, ClingoError> {
let mut subkey = 0;
let name = CString::new(name)?;
if !unsafe { clingo_statistics_map_at(&self.0, key, name.as_ptr(), &mut subkey) } {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_map_at() failed",
));
}
Ok(subkey)
}
pub fn map_add_subkey(
&mut self,
key: u64,
name: &str,
stype: StatisticsType,
) -> Result<u64, ClingoError> {
let mut subkey = 0;
let name = CString::new(name)?;
if !unsafe {
clingo_statistics_map_add_subkey(
&mut self.0,
key,
name.as_ptr(),
stype as clingo_statistics_type_t,
&mut subkey,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_statistics_map_add_subkey() failed",
));
}
Ok(subkey)
}
pub fn value_get(&self, key: u64) -> Result<f64, ClingoError> {
let mut value = 0.0;
if !unsafe { clingo_statistics_value_get(&self.0, key, &mut value) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_size() failed",
));
}
Ok(value)
}
pub fn value_set(&mut self, key: u64, value: f64) -> bool {
unsafe { clingo_statistics_value_set(&mut self.0, key, value) }
}
}
#[derive(Debug)]
pub struct SymbolicAtoms(clingo_symbolic_atoms_t);
impl SymbolicAtoms {
pub fn size(&self) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_symbolic_atoms_size(&self.0, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_size() failed",
));
}
Ok(size)
}
pub fn iter(&self) -> Result<SymbolicAtomsIterator, ClingoError> {
let mut begin = 0;
if !unsafe { clingo_symbolic_atoms_begin(&self.0, std::ptr::null(), &mut begin) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_begin() failed",
));
}
let mut end = 0;
if !unsafe { clingo_symbolic_atoms_end(&self.0, &mut end) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_end() failed",
));
}
Ok(SymbolicAtomsIterator {
cur: begin,
end,
atoms: &self.0,
})
}
pub fn iter_with_signature(
&self,
sig: Signature,
) -> Result<SymbolicAtomsIterator, ClingoError> {
let mut begin = 0;
if !unsafe { clingo_symbolic_atoms_begin(&self.0, &sig.0, &mut begin) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_begin() failed",
));
}
let mut end = 0;
if !unsafe { clingo_symbolic_atoms_end(&self.0, &mut end) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_end() failed",
));
}
Ok(SymbolicAtomsIterator {
cur: begin,
end,
atoms: &self.0,
})
}
pub fn signatures(&self) -> Result<Vec<Signature>, ClingoError> {
let mut size = 0;
if !unsafe { clingo_symbolic_atoms_signatures_size(&self.0, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_signatures_size() failed",
));
}
let mut signatures = vec![Signature(0); size];
if !unsafe {
clingo_symbolic_atoms_signatures(
&self.0,
signatures.as_mut_ptr() as *mut clingo_signature_t,
size,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_signatures() failed",
));
}
Ok(signatures)
}
}
pub struct SymbolicAtomsIterator<'a> {
cur: clingo_symbolic_atom_iterator_t,
end: clingo_symbolic_atom_iterator_t,
atoms: &'a clingo_symbolic_atoms_t,
}
impl<'a> Iterator for SymbolicAtomsIterator<'a> {
type Item = SymbolicAtom<'a>;
fn next(&mut self) -> Option<SymbolicAtom<'a>> {
let mut equal = false;
if !unsafe {
clingo_symbolic_atoms_iterator_is_equal_to(self.atoms, self.cur, self.end, &mut equal)
} {
return None;
}
if equal {
return None;
}
let ret = SymbolicAtom {
cur: self.cur,
atoms: self.atoms,
};
if !unsafe { clingo_symbolic_atoms_next(self.atoms, self.cur, &mut self.cur) } {
panic!(
"Call clingo_symbolic_atoms_next() failed {}{}{}.",
file!(),
line!(),
column!()
);
}
Some(ret)
}
}
pub struct SymbolicAtom<'a> {
cur: clingo_symbolic_atom_iterator_t,
atoms: &'a clingo_symbolic_atoms_t,
}
impl<'a> SymbolicAtom<'a> {
pub fn is_fact(&self) -> Result<bool, ClingoError> {
let mut fact = false;
if !unsafe { clingo_symbolic_atoms_is_fact(self.atoms, self.cur, &mut fact) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_is_fact() failed",
));
}
Ok(fact)
}
pub fn is_external(&self) -> Result<bool, ClingoError> {
let mut external = false;
if !unsafe { clingo_symbolic_atoms_is_external(self.atoms, self.cur, &mut external) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_is_external() failed",
));
}
Ok(external)
}
pub fn symbol(&self) -> Result<Symbol, ClingoError> {
let mut symbol = 0;
if !unsafe { clingo_symbolic_atoms_symbol(self.atoms, self.cur, &mut symbol) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_symbol() failed",
));
}
Ok(Symbol(symbol))
}
pub fn literal(&self) -> Result<SolverLiteral, ClingoError> {
let mut literal = 0;
if !unsafe { clingo_symbolic_atoms_literal(self.atoms, self.cur, &mut literal) } {
return Err(ClingoError::new_internal(
"Call to clingo_symbolic_atoms_literal() failed",
));
}
Ok(SolverLiteral(literal))
}
}
#[derive(Debug)]
pub struct TheoryAtoms(clingo_theory_atoms_t);
impl TheoryAtoms {
pub fn size(&self) -> Result<usize, ClingoError> {
let mut size = 0;
if !unsafe { clingo_theory_atoms_size(&self.0, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_size() failed",
));
}
Ok(size)
}
pub fn iter(&self) -> TheoryAtomsIterator {
TheoryAtomsIterator {
count: 0,
atoms: self,
}
}
pub fn term_type(&self, Id(term): Id) -> Result<TheoryTermType, ClingoError> {
let mut ttype = 0;
if !unsafe { clingo_theory_atoms_term_type(&self.0, term, &mut ttype) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_type() failed",
));
}
TheoryTermType::try_from(ttype as u32)
}
pub fn term_number(&self, Id(term): Id) -> Result<i32, ClingoError> {
let mut number = 0;
if !unsafe { clingo_theory_atoms_term_number(&self.0, term, &mut number) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_number() failed",
));
}
Ok(number)
}
pub fn term_name<'a>(&self, Id(term): Id) -> Result<&'a str, ClingoError> {
let mut char_ptr = std::ptr::null();
if !unsafe { clingo_theory_atoms_term_name(&self.0, term, &mut char_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_name() failed",
));
}
if char_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_theory_atoms_term_name() returned a null pointer.",
});
}
let c_str = unsafe { CStr::from_ptr(char_ptr) };
Ok(c_str.to_str()?)
}
pub fn term_arguments(&self, Id(term): Id) -> Result<&[Id], ClingoError> {
let mut size = 0;
let mut c_ptr = std::ptr::null();
if !unsafe { clingo_theory_atoms_term_arguments(&self.0, term, &mut c_ptr, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_arguments() failed",
));
}
let arguments_ref = unsafe { std::slice::from_raw_parts(c_ptr as *const Id, size) };
Ok(arguments_ref)
}
pub fn term_to_string(&self, Id(term): Id) -> Result<String, ClingoError> {
let mut size = 0;
if !unsafe { clingo_theory_atoms_term_to_string_size(&self.0, term, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_to_string_size() failed",
));
}
let mut string = Vec::with_capacity(size);
let string_ptr = string.as_mut_ptr();
if !unsafe { clingo_theory_atoms_term_to_string(&self.0, term, string_ptr, size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_term_to_string() failed",
));
}
let c_str: &CStr = unsafe { CStr::from_ptr(string_ptr) };
let str_slice: &str = c_str.to_str()?;
Ok(str_slice.to_owned())
}
pub fn element_tuple(&self, Id(element): Id) -> Result<&[Id], ClingoError> {
let mut size = 0;
let mut tuple_ptr = std::ptr::null();
if !unsafe {
clingo_theory_atoms_element_tuple(&self.0, element, &mut tuple_ptr, &mut size)
} {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_element_tuple() failed",
));
}
let tuple_ref = unsafe { std::slice::from_raw_parts(tuple_ptr as *const Id, size) };
Ok(tuple_ref)
}
pub fn element_condition(&self, Id(element): Id) -> Result<&[SolverLiteral], ClingoError> {
let mut size = 0;
let mut condition_ptr = std::ptr::null();
if !unsafe {
clingo_theory_atoms_element_condition(&self.0, element, &mut condition_ptr, &mut size)
} {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_element_condition() failed",
));
}
let condition_ref =
unsafe { std::slice::from_raw_parts(condition_ptr as *const SolverLiteral, size) };
Ok(condition_ref)
}
pub fn element_condition_id(&self, Id(element): Id) -> Result<SolverLiteral, ClingoError> {
let condition_ptr = std::ptr::null_mut();
if !unsafe { clingo_theory_atoms_element_condition_id(&self.0, element, condition_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_element_condition_id() failed",
));
}
if condition_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_theory_atoms_element_condition_id() returned a null pointer.",
});
}
Ok(SolverLiteral(unsafe { *condition_ptr }))
}
pub fn element_to_string(&self, Id(element): Id) -> Result<String, ClingoError> {
let mut size = 0;
if !unsafe { clingo_theory_atoms_element_to_string_size(&self.0, element, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_element_to_string_size() failed",
));
}
let mut string = Vec::with_capacity(size);
let string_ptr = string.as_mut_ptr();
if !unsafe { clingo_theory_atoms_element_to_string(&self.0, element, string_ptr, size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_element_to_string() failed",
));
}
let c_str: &CStr = unsafe { CStr::from_ptr(string_ptr) };
let str_slice: &str = c_str.to_str()?;
Ok(str_slice.to_owned())
}
pub fn atom_term(&self, Id(atom): Id) -> Result<Id, ClingoError> {
let mut term = 0;
if !unsafe { clingo_theory_atoms_atom_term(&self.0, atom, &mut term) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_term() failed",
));
}
Ok(Id(term))
}
pub fn atom_elements(&self, Id(atom): Id) -> Result<&[Id], ClingoError> {
let mut size = 0;
let mut elements_ptr = std::ptr::null() as *const clingo_id_t;
if !unsafe {
clingo_theory_atoms_atom_elements(&self.0, atom, &mut elements_ptr, &mut size)
} {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_elements() failed",
));
}
let elements = unsafe { std::slice::from_raw_parts(elements_ptr as *const Id, size) };
Ok(elements)
}
pub fn atom_has_guard(&self, Id(atom): Id) -> Result<bool, ClingoError> {
let mut has_guard = false;
if !unsafe { clingo_theory_atoms_atom_has_guard(&self.0, atom, &mut has_guard) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_has_guard() failed",
));
}
Ok(has_guard)
}
pub fn atom_guard(&self, Id(atom): Id) -> Result<(&str, Id), ClingoError> {
let mut c_ptr = std::ptr::null() as *const c_char;
let mut term = 0;
if !unsafe { clingo_theory_atoms_atom_guard(&self.0, atom, &mut c_ptr, &mut term) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_guard() failed",
));
}
if c_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_theory_atoms_atom_guard() returned a null pointer.",
});
}
let cstr = unsafe { CStr::from_ptr(c_ptr) };
Ok((cstr.to_str()?, Id(term)))
}
pub fn atom_literal(&self, Id(atom): Id) -> Result<SolverLiteral, ClingoError> {
let mut literal = 0;
if !unsafe { clingo_theory_atoms_atom_literal(&self.0, atom, &mut literal) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_literal() failed",
));
}
Ok(SolverLiteral(literal))
}
pub fn atom_to_string(&self, Id(atom): Id) -> Result<String, ClingoError> {
let mut size = 0;
if !unsafe { clingo_theory_atoms_atom_to_string_size(&self.0, atom, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_to_string_size() failed",
));
}
let mut string = Vec::with_capacity(size);
let string_ptr = string.as_mut_ptr();
if !unsafe { clingo_theory_atoms_atom_to_string(&self.0, atom, string_ptr, size) } {
return Err(ClingoError::new_internal(
"Call to clingo_theory_atoms_atom_to_string() failed",
));
}
let c_str: &CStr = unsafe { CStr::from_ptr(string_ptr) };
let str_slice: &str = c_str.to_str()?;
Ok(str_slice.to_owned())
}
}
pub struct TheoryAtomsIterator<'a> {
count: usize,
atoms: &'a TheoryAtoms,
}
impl<'a> Iterator for TheoryAtomsIterator<'a> {
type Item = Id;
fn next(&mut self) -> Option<Id> {
if self.count < self.atoms.size().unwrap() {
let ret = Id(self.count as clingo_id_t);
self.count += 1;
Some(ret)
} else {
None
}
}
}
#[derive(Debug)]
pub struct Model(clingo_model_t);
impl Model {
pub fn model_type(&self) -> Result<ModelType, ClingoError> {
let mut mtype = 0;
if !unsafe { clingo_model_type(&self.0, &mut mtype) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_type() failed",
));
}
ModelType::try_from(mtype as u32)
}
pub fn number(&self) -> Result<u64, ClingoError> {
let mut number = 0;
if !unsafe { clingo_model_number(&self.0, &mut number) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_number() failed",
));
}
Ok(number)
}
pub fn symbols(&self, show: ShowType) -> Result<Vec<Symbol>, ClingoError> {
let mut size: usize = 0;
if !unsafe { clingo_model_symbols_size(&self.0, show.bits(), &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_symbols_size() failed",
));
}
let symbols = vec![Symbol(0); size];
if !unsafe {
clingo_model_symbols(
&self.0,
show.bits(),
symbols.as_ptr() as *mut clingo_symbol_t,
size,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_model_symbols() failed",
));
}
Ok(symbols)
}
pub fn contains(&self, Symbol(atom): Symbol) -> Result<bool, ClingoError> {
let mut contained = false;
if !unsafe { clingo_model_contains(&self.0, atom, &mut contained) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_contains() failed",
));
}
Ok(contained)
}
pub fn is_true(&self, literal: SolverLiteral) -> Result<bool, ClingoError> {
let mut is_true = false;
if !unsafe { clingo_model_is_true(&self.0, literal.0, &mut is_true) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_is_true() failed",
));
}
Ok(is_true)
}
pub fn cost(&self) -> Result<Vec<i64>, ClingoError> {
let mut size: usize = 0;
if !unsafe { clingo_model_cost_size(&self.0, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_cost_size() failed",
));
}
let mut cost = vec![0; size];
if !unsafe { clingo_model_cost(&self.0, cost.as_mut_ptr(), size) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_cost() failed",
));
}
Ok(cost)
}
pub fn optimality_proven(&self) -> Result<bool, ClingoError> {
let mut proven = false;
if !unsafe { clingo_model_optimality_proven(&self.0, &mut proven) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_optimality_proven() failed",
));
}
Ok(proven)
}
pub fn thread_id(&self) -> Result<Id, ClingoError> {
let mut id = 0;
if !unsafe { clingo_model_thread_id(&self.0, &mut id) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_thread_id() failed",
));
}
Ok(Id(id))
}
pub fn extend(&mut self, symbols: &[Symbol]) -> bool {
unsafe {
clingo_model_extend(
&mut self.0,
symbols.as_ptr() as *const clingo_symbol_t,
symbols.len(),
)
}
}
pub fn context(&self) -> Result<&mut SolveControl, ClingoError> {
let control_ptr = std::ptr::null_mut();
if !unsafe { clingo_model_context(&self.0, control_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_model_context() failed",
));
}
if control_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_model_context() returned a null pointer.",
});
}
unsafe { Ok(&mut *(control_ptr as *mut SolveControl)) }
}
}
#[derive(Debug)]
pub struct SolveControl(clingo_solve_control_t);
impl SolveControl {
pub fn add_clause(&mut self, clause: &[SolverLiteral]) -> Result<(), ClingoError> {
if !unsafe {
clingo_solve_control_add_clause(
&mut self.0,
clause.as_ptr() as *const clingo_literal_t,
clause.len(),
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_solve_control_add_clause() failed",
));
}
Ok(())
}
pub fn symbolic_atoms(&self) -> Result<&SymbolicAtoms, ClingoError> {
let mut atoms = std::ptr::null() as *const clingo_symbolic_atoms_t;
if !unsafe { clingo_solve_control_symbolic_atoms(&self.0, &mut atoms) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_level() failed",
));
}
match unsafe { (atoms as *const SymbolicAtoms).as_ref() } {
Some(stm) => Ok(stm),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &SymbolicAtoms.",
}),
}
}
}
#[derive(Debug)]
pub struct Assignment(clingo_assignment_t);
impl Assignment {
pub fn decision_level(&self) -> u32 {
unsafe { clingo_assignment_decision_level(&self.0) }
}
pub fn root_level(&self) -> u32 {
unsafe { clingo_assignment_root_level(&self.0) }
}
pub fn has_conflict(&self) -> bool {
unsafe { clingo_assignment_has_conflict(&self.0) }
}
pub fn has_literal(&self, literal: SolverLiteral) -> bool {
unsafe { clingo_assignment_has_literal(&self.0, literal.0) }
}
pub fn level(&self, literal: SolverLiteral) -> Result<u32, ClingoError> {
let mut level = 0;
if !unsafe { clingo_assignment_level(&self.0, literal.0, &mut level) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_level() failed",
));
}
Ok(level)
}
pub fn decision(&self, level: u32) -> Result<SolverLiteral, ClingoError> {
let mut lit = 0;
if !unsafe { clingo_assignment_decision(&self.0, level, &mut lit) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_decision() failed",
));
}
Ok(SolverLiteral(lit))
}
pub fn is_fixed(&self, literal: SolverLiteral) -> Result<bool, ClingoError> {
let mut is_fixed = false;
if !unsafe { clingo_assignment_is_fixed(&self.0, literal.0, &mut is_fixed) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_is_fixed() failed",
));
}
Ok(is_fixed)
}
pub fn is_true(&self, literal: SolverLiteral) -> Result<bool, ClingoError> {
let mut is_true = false;
if !unsafe { clingo_assignment_is_true(&self.0, literal.0, &mut is_true) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_is_true() failed",
));
}
Ok(is_true)
}
pub fn is_false(&self, literal: SolverLiteral) -> Result<bool, ClingoError> {
let mut is_false = false;
if !unsafe { clingo_assignment_is_false(&self.0, literal.0, &mut is_false) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_is_false() failed",
));
}
Ok(is_false)
}
pub fn truth_value(&self, literal: SolverLiteral) -> Result<TruthValue, ClingoError> {
let mut value = 0;
if !unsafe { clingo_assignment_truth_value(&self.0, literal.0, &mut value) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_truth_value() failed",
));
}
TruthValue::try_from(value as u32)
}
pub fn size(&self) -> usize {
unsafe { clingo_assignment_size(&self.0) }
}
pub fn at(&self, offset: usize) -> Result<SolverLiteral, ClingoError> {
let mut lit = 0;
if !unsafe { clingo_assignment_at(&self.0, offset, &mut lit) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_at() failed",
));
}
Ok(SolverLiteral(lit))
}
pub fn is_total(&self) -> bool {
unsafe { clingo_assignment_is_total(&self.0) }
}
pub fn trail_size(&self) -> Result<u32, ClingoError> {
let mut size = 0;
if !unsafe { clingo_assignment_trail_size(&self.0, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_trail_size() failed",
));
}
Ok(size)
}
pub fn trail_begin(&self, level: u32) -> Result<u32, ClingoError> {
let mut offset = 0;
if !unsafe { clingo_assignment_trail_begin(&self.0, level, &mut offset) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_trail_begin() failed",
));
}
Ok(offset)
}
pub fn trail_end(&self, level: u32) -> Result<u32, ClingoError> {
let mut offset = 0;
if !unsafe { clingo_assignment_trail_end(&self.0, level, &mut offset) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_trail_end() failed",
));
}
Ok(offset)
}
pub fn trail_at(&self, offset: u32) -> Result<SolverLiteral, ClingoError> {
let mut lit = 0;
if !unsafe { clingo_assignment_trail_at(&self.0, offset, &mut lit) } {
return Err(ClingoError::new_internal(
"Call to clingo_assignment_trail_at() failed",
));
}
Ok(SolverLiteral(lit))
}
}
#[derive(Debug)]
pub struct PropagateControl(clingo_propagate_control_t);
impl PropagateControl {
pub fn thread_id(&self) -> u32 {
unsafe { clingo_propagate_control_thread_id(&self.0) }
}
pub fn assignment(&self) -> Result<&Assignment, ClingoError> {
match unsafe {
(clingo_propagate_control_assignment(&self.0) as *const Assignment).as_ref()
} {
Some(stm) => Ok(stm),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &Assignment.",
}),
}
}
pub fn assignment_mut(&self) -> Result<&mut Assignment, ClingoError> {
match unsafe { (clingo_propagate_control_assignment(&self.0) as *mut Assignment).as_mut() }
{
Some(stm) => Ok(stm),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &mut Assignment.",
}),
}
}
pub fn add_literal(&mut self, result: &mut SolverLiteral) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_control_add_literal(&mut self.0, &mut result.0) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_control_add_literal() failed",
));
}
Ok(())
}
pub fn add_watch(&mut self, literal: SolverLiteral) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_control_add_watch(&mut self.0, literal.0) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_control_add_watch() failed",
));
}
Ok(())
}
pub fn has_watch(&self, literal: SolverLiteral) -> bool {
unsafe { clingo_propagate_control_has_watch(&self.0, literal.0) }
}
pub fn remove_watch(&mut self, literal: SolverLiteral) {
unsafe { clingo_propagate_control_remove_watch(&mut self.0, literal.0) }
}
pub fn add_clause(
&mut self,
clause: &[SolverLiteral],
ctype: ClauseType,
) -> Result<bool, ClingoError> {
let mut result = false;
if !unsafe {
clingo_propagate_control_add_clause(
&mut self.0,
clause.as_ptr() as *const clingo_literal_t,
clause.len(),
ctype as clingo_clause_type_t,
&mut result,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_control_add_clause() failed",
));
}
Ok(result)
}
pub fn propagate(&mut self) -> Result<bool, ClingoError> {
let mut result = false;
if !unsafe { clingo_propagate_control_propagate(&mut self.0, &mut result) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_control_propagate() failed",
));
}
Ok(result)
}
}
#[derive(Debug)]
pub struct PropagateInit(clingo_propagate_init_t);
impl PropagateInit {
pub fn solver_literal(
&self,
SolverLiteral(aspif_literal): SolverLiteral,
) -> Result<SolverLiteral, ClingoError> {
let mut solver_literal = 0;
if !unsafe {
clingo_propagate_init_solver_literal(&self.0, aspif_literal, &mut solver_literal)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_solver_literal() failed",
));
}
Ok(SolverLiteral(solver_literal))
}
pub fn add_watch(
&mut self,
SolverLiteral(solver_literal): SolverLiteral,
) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_init_add_watch(&mut self.0, solver_literal) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_watch() failed",
));
}
Ok(())
}
pub fn add_watch_to_thread(
&mut self,
SolverLiteral(solver_literal): SolverLiteral,
thread_id: u32,
) -> Result<(), ClingoError> {
if !unsafe {
clingo_propagate_init_add_watch_to_thread(&mut self.0, solver_literal, thread_id)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_watch_to_thread() failed",
));
}
Ok(())
}
pub fn symbolic_atoms(&self) -> Result<&SymbolicAtoms, ClingoError> {
let mut atoms_ptr = std::ptr::null() as *const clingo_symbolic_atoms_t;
if !unsafe { clingo_propagate_init_symbolic_atoms(&self.0, &mut atoms_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_symbolic_atoms() failed",
));
}
match unsafe { (atoms_ptr as *const SymbolicAtoms).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &SymbolicAtoms.",
}),
}
}
pub fn theory_atoms(&self) -> Result<&TheoryAtoms, ClingoError> {
let mut atoms_ptr = std::ptr::null() as *const clingo_theory_atoms_t;
if !unsafe { clingo_propagate_init_theory_atoms(&self.0, &mut atoms_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_symbolic_atoms() failed",
));
}
match unsafe { (atoms_ptr as *const TheoryAtoms).as_ref() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &TheoryAtoms.",
}),
}
}
pub fn number_of_threads(&self) -> usize {
(unsafe { clingo_propagate_init_number_of_threads(&self.0) }) as usize
}
pub fn set_check_mode(&mut self, mode: PropagatorCheckMode) {
unsafe {
clingo_propagate_init_set_check_mode(
&mut self.0,
mode as clingo_propagator_check_mode_t,
)
}
}
pub fn get_check_mode(&self) -> Result<PropagatorCheckMode, ClingoError> {
PropagatorCheckMode::try_from(
unsafe { clingo_propagate_init_get_check_mode(&self.0) } as u32
)
}
pub fn assignment(&self) -> Result<&Assignment, ClingoError> {
match unsafe { (clingo_propagate_init_assignment(&self.0) as *const Assignment).as_ref() } {
Some(stm) => Ok(stm),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &mut Assignment.",
}),
}
}
pub fn add_literal(&mut self, freeze: bool) -> Result<&mut SolverLiteral, ClingoError> {
let literal_ptr = std::ptr::null_mut() as *mut clingo_literal_t;
if !unsafe { clingo_propagate_init_add_literal(&mut self.0, freeze, literal_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_literal() failed",
));
}
match unsafe { (literal_ptr as *mut SolverLiteral).as_mut() } {
Some(x) => Ok(x),
None => Err(ClingoError::FFIError {
msg: "Tried casting a null pointer to &mutSolverLiteral.",
}),
}
}
pub fn add_clause(&mut self, clause: &[SolverLiteral]) -> Result<bool, ClingoError> {
let mut result = false;
if !unsafe {
clingo_propagate_init_add_clause(
&mut self.0,
clause.as_ptr() as *const clingo_literal_t,
clause.len(),
&mut result,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_clause() failed",
));
}
Ok(result)
}
pub fn add_weight_constraint(
&mut self,
literal: SolverLiteral,
literals: &[WeightedLiteral],
bound: i32,
wctype: WeigthConstraintType,
compare_equal: bool,
) -> Result<bool, ClingoError> {
let mut result = false;
if !unsafe {
clingo_propagate_init_add_weight_constraint(
&mut self.0,
literal.0,
literals.as_ptr() as *const clingo_weighted_literal_t,
literals.len(),
bound,
wctype as i32,
compare_equal,
&mut result,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_weight_constraint() failed",
));
}
Ok(result)
}
pub fn add_minimize(
&mut self,
literal: SolverLiteral,
weight: i32,
priority: i32,
) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_init_add_minimize(&mut self.0, literal.0, weight, priority) }
{
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_add_minimize() failed",
));
}
Ok(())
}
pub fn propagate(&mut self) -> Result<bool, ClingoError> {
let mut result = false;
if !unsafe { clingo_propagate_init_propagate(&mut self.0, &mut result) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_propagate() failed",
));
}
Ok(result)
}
pub fn remove_watch(&mut self, literal: &SolverLiteral) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_init_remove_watch(&mut self.0, literal.0) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_remove_watch() failed",
));
}
Ok(())
}
pub fn remove_watch_from_thread(
&mut self,
literal: &SolverLiteral,
thread_id: u32,
) -> Result<(), ClingoError> {
if !unsafe {
clingo_propagate_init_remove_watch_from_thread(&mut self.0, literal.0, thread_id)
} {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_remove_watch_from_thread() failed",
));
}
Ok(())
}
pub fn freeze_literal(&mut self, literal: &SolverLiteral) -> Result<(), ClingoError> {
if !unsafe { clingo_propagate_init_freeze_literal(&mut self.0, literal.0) } {
return Err(ClingoError::new_internal(
"Call to clingo_propagate_init_freeze_literal() failed",
));
}
Ok(())
}
}
#[derive(Debug)]
pub struct GenericSolveHandle<C: ControlCtx, E: SolveEventHandler> {
handle: NonNull<clingo_solve_handle_t>,
ctl: GenericControl<C>,
_event_handler: Box<E>,
}
pub type SolveHandle = GenericSolveHandle<DefaultCtx, defaults::Non>;
impl<C: ControlCtx, E: SolveEventHandler> GenericSolveHandle<C, E> {
pub fn get(&mut self) -> Result<SolveResult, ClingoError> {
let mut result = 0;
if !unsafe { clingo_solve_handle_get(self.handle.as_ptr(), &mut result) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_get() failed",
));
}
if let Some(res) = SolveResult::from_bits(result) {
Ok(res)
} else {
eprintln!("Unknown bitflag in clingo_solve_result: {}.", result);
Err(ClingoError::FFIError {
msg: "Unknown bitflag in clingo_solve_result.",
})
}
}
pub fn wait(&mut self, timeout: Duration) -> bool {
let mut result = false;
let timeout_secs = timeout.as_secs_f64();
unsafe { clingo_solve_handle_wait(self.handle.as_ptr(), timeout_secs, &mut result) }
result
}
pub fn model(&mut self) -> Result<Option<&Model>, ClingoError> {
let mut model = std::ptr::null_mut() as *const clingo_model_t;
if !unsafe { clingo_solve_handle_model(self.handle.as_ptr(), &mut model) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_model() failed",
));
}
Ok(unsafe { (model as *const Model).as_ref() })
}
pub fn model_mut(&mut self) -> Result<Option<&mut Model>, ClingoError> {
let mut model = std::ptr::null_mut() as *const clingo_model_t;
if !unsafe { clingo_solve_handle_model(self.handle.as_ptr(), &mut model) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_model() failed",
));
}
Ok(unsafe { (model as *mut Model).as_mut() })
}
pub fn core(&mut self) -> Result<Vec<SolverLiteral>, ClingoError> {
let mut literal_ptr = std::ptr::null();
let mut size: usize = 0;
if !unsafe { clingo_solve_handle_core(self.handle.as_ptr(), &mut literal_ptr, &mut size) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_core() failed",
));
}
let mut literals = Vec::<SolverLiteral>::with_capacity(size);
for _ in 0..size {
if literal_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_solve_handle_core() returned a null pointer.",
});
}
let nliteral = unsafe { *literal_ptr };
literals.push(SolverLiteral(nliteral));
literal_ptr = unsafe { literal_ptr.offset(1) };
}
Ok(literals)
}
pub fn resume(&mut self) -> Result<(), ClingoError> {
if !unsafe { clingo_solve_handle_resume(self.handle.as_ptr()) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_resume() failed",
));
}
Ok(())
}
pub fn cancel(&mut self) -> Result<(), ClingoError> {
if !unsafe { clingo_solve_handle_cancel(self.handle.as_ptr()) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_cancel() failed",
));
}
Ok(())
}
pub fn close(self) -> Result<GenericControl<C>, ClingoError> {
if !unsafe { clingo_solve_handle_close(self.handle.as_ptr()) } {
return Err(ClingoError::new_internal(
"Call to clingo_solve_handle_close() failed",
));
}
Ok(self.ctl)
}
}
pub struct OptimalModels<C: ControlCtx, E: SolveEventHandler>(GenericSolveHandle<C, E>);
impl<C: ControlCtx, E: SolveEventHandler> Iterator for OptimalModels<C, E> {
type Item = MModel;
fn next(&mut self) -> Option<Self::Item> {
loop {
self.0.resume().expect("Failed resume on solve handle.");
match self.0.model() {
Ok(Some(model)) => {
if model.optimality_proven().unwrap() {
let symbols = model.symbols(ShowType::SHOWN).unwrap();
let cost = model.cost().unwrap();
return Some(MModel {
symbols,
cost,
model_type: model.model_type().unwrap(),
number: model.number().unwrap(),
});
}
}
Ok(None) => {
return None;
}
Err(e) => panic!("{}", e),
}
}
}
}
pub struct AllModels<C: ControlCtx, E: SolveEventHandler>(GenericSolveHandle<C, E>);
impl<C: ControlCtx, E: SolveEventHandler> Iterator for AllModels<C, E> {
type Item = MModel;
fn next(&mut self) -> Option<Self::Item> {
loop {
self.0.resume().expect("Failed resume on solve handle.");
match self.0.model() {
Ok(Some(model)) => {
let symbols = model.symbols(ShowType::SHOWN).unwrap();
let cost = model.cost().unwrap();
return Some(MModel {
symbols,
cost,
model_type: model.model_type().unwrap(),
number: model.number().unwrap(),
});
}
Ok(None) => {
return None;
}
Err(e) => panic!("{}", e),
}
}
}
}
pub struct MModel {
pub symbols: Vec<Symbol>,
pub cost: Vec<i64>,
pub model_type: ModelType,
pub number: u64,
}
pub fn add_string(string: &str) -> Result<&'static str, ClingoError> {
let in_cstr = CString::new(string)?;
let mut out_ptr = std::ptr::null() as *const c_char;
if !unsafe { clingo_add_string(in_cstr.as_ptr(), &mut out_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_add_string() failed",
));
}
if out_ptr.is_null() {
return Err(ClingoError::FFIError {
msg: "clingo_add_string returned a null pointer.",
});
}
let out_cstr = unsafe { CStr::from_ptr(out_ptr) };
Ok(out_cstr.to_str()?)
}
fn internalize_string(string: &str) -> Result<*const c_char, ClingoError> {
let in_cstr = CString::new(string)?;
let mut out_ptr = std::ptr::null() as *const c_char;
if !unsafe { clingo_add_string(in_cstr.as_ptr(), &mut out_ptr) } {
return Err(ClingoError::new_internal(
"Call to clingo_add_string() failed",
));
}
if out_ptr.is_null() {
Err(ClingoError::FFIError {
msg: "clingo_add_string returned a null pointer.",
})?
}
Ok(out_ptr)
}
pub fn parse_term(string: &str) -> Result<Symbol, ClingoError> {
let c_str = CString::new(string)?;
let mut symbol = 0;
if !unsafe { clingo_parse_term(c_str.as_ptr(), None, std::ptr::null_mut(), 0, &mut symbol) } {
return Err(ClingoError::new_internal(
"Call to clingo_parse_term() failed",
));
}
Ok(Symbol(symbol))
}
pub fn parse_term_with_logger<L: Logger>(
string: &str,
logger: &mut L,
message_limit: u32,
) -> Result<Symbol, ClingoError> {
let c_str = CString::new(string)?;
let logger = logger as *mut L;
let mut symbol = 0;
if !unsafe {
clingo_parse_term(
c_str.as_ptr(),
Some(unsafe_logging_callback::<L> as LoggingCallback),
logger as *mut c_void,
message_limit,
&mut symbol,
)
} {
return Err(ClingoError::new_internal(
"Call to clingo_parse_term() failed",
));
}
Ok(Symbol(symbol))
}
pub trait GroundProgramObserver {
fn init_program(&mut self, _incremental: bool) -> bool {
true
}
fn begin_step(&mut self) -> bool {
true
}
fn end_step(&mut self) -> bool {
true
}
fn rule(&mut self, _choice: bool, _head: &[Atom], _body: &[SolverLiteral]) -> bool {
true
}
fn weight_rule(
&mut self,
_choice: bool,
_head: &[Atom],
_lower_bound: i32,
_body: &[WeightedLiteral],
) -> bool {
true
}
fn minimize(&mut self, _priority: i32, _literals: &[WeightedLiteral]) -> bool {
true
}
fn project(&mut self, _atoms: &[Atom]) -> bool {
true
}
fn output_atom(&mut self, _symbol: Symbol, _atom: Atom) -> bool {
true
}
fn output_term(&mut self, _symbol: Symbol, _condition: &[SolverLiteral]) -> bool {
true
}
fn output_csp(&mut self, _symbol: Symbol, _value: i32, _condition: &[SolverLiteral]) -> bool {
true
}
fn external(&mut self, _atom: Atom, _type_: ExternalType) -> bool {
true
}
fn assume(&mut self, _literals: &[SolverLiteral]) -> bool {
true
}
fn heuristic(
&mut self,
_atom: Atom,
_type_: HeuristicType,
_bias: i32,
_priority: u32,
_condition: &[SolverLiteral],
) -> bool {
true
}
fn acyc_edge(&mut self, _node_u: i32, _node_v: i32, _condition: &[SolverLiteral]) -> bool {
true
}
fn theory_term_number(&mut self, _term_id: Id, _number: i32) -> bool {
true
}
fn theory_term_string(&mut self, _term_id: Id, _name: &str) -> bool {
true
}
fn theory_term_compound(
&mut self,
_term_id: Id,
_name_id_or_type: i32,
_arguments: &[Id],
) -> bool {
true
}
fn theory_element(
&mut self,
_element_id: Id,
_terms: &[Id],
_condition: &[SolverLiteral],
) -> bool {
true
}
fn theory_atom(&mut self, _atom_id_or_zero: Id, _term_id: Id, _elements: &[Id]) -> bool {
true
}
fn theory_atom_with_guard(
&mut self,
_atom_id_or_zero: Id,
_term_id: Id,
_elements: &[Id],
_operator_id: Id,
_right_hand_side_id: Id,
) -> bool {
true
}
}
unsafe extern "C" fn unsafe_init_program<T: GroundProgramObserver>(
incremental: bool,
gpo: *mut c_void,
) -> bool {
if let Some(gpo) = (gpo as *mut T).as_mut() {
gpo.init_program(incremental)
} else {
set_internal_error(
ErrorType::Runtime,
"unsafe_init_program tried casting a null pointer to &mut GroundProgramObserver.",
);
false
}
}
unsafe extern "C" fn unsafe_begin_step<T: GroundProgramObserver>(gpo: *mut c_void) -> bool {
if let Some(gpo) = (gpo as *mut T).as_mut() {
gpo.begin_step()
} else {
set_internal_error(
ErrorType::Runtime,
"unsafe_begin_step tried casting a null pointer to &mut GroundProgramObserver.",
);
false
}
}
unsafe extern "C" fn unsafe_end_step<T: GroundProgramObserver>(gpo: *mut c_void) -> bool {
if let Some(gpo) = (gpo as *mut T).as_mut() {
gpo.end_step()
} else {
set_internal_error(
ErrorType::Runtime,
"unsafe_end_step tried casting a null pointer to &mut GroundProgramObserver.",
);
false
}
}
unsafe extern "C" fn unsafe_rule<T: GroundProgramObserver>(
choice: bool,
head: *const clingo_atom_t,
head_size: usize,
body: *const clingo_literal_t,
body_size: usize,
gpo: *mut c_void,
) -> bool {
if (head_size > 0 && head.is_null()) | (body_size > 0 && body.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_rule() got a null pointer.");
return false;
}
let head = std::slice::from_raw_parts(head as *const Atom, head_size);
let body = std::slice::from_raw_parts(body as *const SolverLiteral, body_size);
let gpo = &mut *(gpo as *mut T);
gpo.rule(choice, head, body)
}
unsafe extern "C" fn unsafe_minimize<T: GroundProgramObserver>(
priority: clingo_weight_t,
literals: *const clingo_weighted_literal_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && literals.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_minimize() got a null pointer.");
return false;
}
let literals = std::slice::from_raw_parts(literals as *const WeightedLiteral, size);
let gpo = &mut *(gpo as *mut T);
gpo.minimize(priority, literals)
}
unsafe extern "C" fn unsafe_project<T: GroundProgramObserver>(
atoms: *const clingo_atom_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && atoms.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_project() got a null pointer.");
return false;
}
let atoms = std::slice::from_raw_parts(atoms as *const Atom, size);
let gpo = &mut *(gpo as *mut T);
gpo.project(atoms)
}
unsafe extern "C" fn unsafe_weight_rule<T: GroundProgramObserver>(
choice: bool,
head: *const clingo_atom_t,
head_size: usize,
lower_bound: clingo_weight_t,
body: *const clingo_weighted_literal_t,
body_size: usize,
gpo: *mut c_void,
) -> bool {
if (head_size > 0 && head.is_null()) | (body_size > 0 && body.is_null()) | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_weight_rule() got a null pointer.",
);
return false;
}
let head = std::slice::from_raw_parts(head as *const Atom, head_size);
let body = std::slice::from_raw_parts(body as *const WeightedLiteral, body_size);
let gpo = &mut *(gpo as *mut T);
gpo.weight_rule(choice, head, lower_bound, body)
}
unsafe extern "C" fn unsafe_output_atom<T: GroundProgramObserver>(
symbol: clingo_symbol_t,
atom: clingo_atom_t,
gpo: *mut c_void,
) -> bool {
if let Some(gpo) = (gpo as *mut T).as_mut() {
gpo.output_atom(Symbol(symbol), Atom(atom))
} else {
set_internal_error(
ErrorType::Runtime,
"unsafe_output_atom() tried casting a null pointer to &mut GroundProgramObserver.",
);
false
}
}
unsafe extern "C" fn unsafe_output_term<T: GroundProgramObserver>(
symbol: clingo_symbol_t,
condition: *const clingo_literal_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && condition.is_null()) | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_output_term() got a null pointer.",
);
return false;
}
let condition = std::slice::from_raw_parts(condition as *const SolverLiteral, size);
let gpo = &mut *(gpo as *mut T);
gpo.output_term(Symbol(symbol), condition)
}
unsafe extern "C" fn unsafe_external<T: GroundProgramObserver>(
atom: clingo_atom_t,
etype: clingo_external_type_t,
gpo: *mut c_void,
) -> bool {
if gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_external() got a null pointer.");
return false;
}
let gpo = &mut *(gpo as *mut T);
match ExternalType::try_from(etype as u32) {
Err(e) => {
eprintln!("Error in unsafe_external(): {}.", e);
set_internal_error(ErrorType::Runtime, "Error in unsafe_external().");
false
}
Ok(etype) => gpo.external(Atom(atom), etype),
}
}
unsafe extern "C" fn unsafe_assume<T: GroundProgramObserver>(
literals: *const clingo_literal_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && literals.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_assume() got a null pointer.");
return false;
}
let literals = std::slice::from_raw_parts(literals as *const SolverLiteral, size);
let gpo = &mut *(gpo as *mut T);
gpo.assume(literals)
}
unsafe extern "C" fn unsafe_heuristic<T: GroundProgramObserver>(
atom: clingo_atom_t,
htype: clingo_heuristic_type_t,
bias: ::std::os::raw::c_int,
priority: ::std::os::raw::c_uint,
condition: *const clingo_literal_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && condition.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_heuristic() got a null pointer.");
return false;
}
let condition = std::slice::from_raw_parts(condition as *const SolverLiteral, size);
let gpo = &mut *(gpo as *mut T);
match HeuristicType::try_from(htype as u32) {
Err(e) => {
eprintln!("Error in unsafe_heuristic(): {}.", e);
set_internal_error(ErrorType::Runtime, "Error in unsafe_heuristic().");
false
}
Ok(htype) => gpo.heuristic(Atom(atom), htype, bias, priority, condition),
}
}
unsafe extern "C" fn unsafe_acyc_edge<T: GroundProgramObserver>(
node_u: ::std::os::raw::c_int,
node_v: ::std::os::raw::c_int,
condition: *const clingo_literal_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && condition.is_null()) | gpo.is_null() {
set_internal_error(ErrorType::Runtime, "unsafe_heuristic() got a null pointer.");
return false;
}
let condition = std::slice::from_raw_parts(condition as *const SolverLiteral, size);
let gpo = &mut *(gpo as *mut T);
gpo.acyc_edge(node_u, node_v, condition)
}
unsafe extern "C" fn unsafe_theory_term_number<T: GroundProgramObserver>(
term_id: clingo_id_t,
number: ::std::os::raw::c_int,
gpo: *mut c_void,
) -> bool {
if let Some(gpo) = (gpo as *mut T).as_mut() {
gpo.theory_term_number(Id(term_id), number)
} else {
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_term_number tried casting a null pointer to &mut GroundProgramObserver.",
);
false
}
}
unsafe extern "C" fn unsafe_theory_term_string<T: GroundProgramObserver>(
term_id: clingo_id_t,
name: *const c_char,
gpo: *mut c_void,
) -> bool {
if name.is_null() | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_term_string() got a null pointer.",
);
return false;
}
let name = CStr::from_ptr(name);
let gpo = &mut *(gpo as *mut T);
match name.to_str() {
Ok(name) => gpo.theory_term_string(Id(term_id), name),
Err(e) => {
eprintln!("Utf8Error in unsafe theory_term_string: {}", e);
set_internal_error(
ErrorType::Runtime,
"Utf8Error in unsafe theory_term_string.",
);
false
}
}
}
unsafe extern "C" fn unsafe_theory_term_compound<T: GroundProgramObserver>(
term_id: clingo_id_t,
name_id_or_type: ::std::os::raw::c_int,
arguments: *const clingo_id_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && arguments.is_null()) | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_term_compound() got a null pointer.",
);
return false;
}
let arguments = std::slice::from_raw_parts(arguments as *const Id, size);
let gpo = &mut *(gpo as *mut T);
gpo.theory_term_compound(Id(term_id), name_id_or_type, arguments)
}
unsafe extern "C" fn unsafe_theory_element<T: GroundProgramObserver>(
element_id: clingo_id_t,
terms: *const clingo_id_t,
terms_size: usize,
condition: *const clingo_literal_t,
condition_size: usize,
gpo: *mut c_void,
) -> bool {
if (terms_size > 0 && terms.is_null())
| (condition_size > 0 && condition.is_null())
| gpo.is_null()
{
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_element() got a null pointer.",
);
return false;
}
let terms = std::slice::from_raw_parts(terms as *const Id, terms_size);
let condition = std::slice::from_raw_parts(condition as *const SolverLiteral, condition_size);
let gpo = &mut *(gpo as *mut T);
gpo.theory_element(Id(element_id), terms, condition)
}
unsafe extern "C" fn unsafe_theory_atom<T: GroundProgramObserver>(
atom_id_or_zero: clingo_id_t,
term_id: clingo_id_t,
elements: *const clingo_id_t,
size: usize,
gpo: *mut c_void,
) -> bool {
if (size > 0 && elements.is_null()) | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_atom() got a null pointer.",
);
return false;
}
let elements = std::slice::from_raw_parts(elements as *const Id, size);
let gpo = &mut *(gpo as *mut T);
gpo.theory_atom(Id(atom_id_or_zero), Id(term_id), elements)
}
unsafe extern "C" fn unsafe_theory_atom_with_guard<T: GroundProgramObserver>(
atom_id_or_zero: clingo_id_t,
term_id: clingo_id_t,
elements: *const clingo_id_t,
size: usize,
operator_id: clingo_id_t,
right_hand_side_id: clingo_id_t,
gpo: *mut c_void,
) -> bool {
if (size > 0 && elements.is_null()) | gpo.is_null() {
set_internal_error(
ErrorType::Runtime,
"unsafe_theory_atom_with_guard() got a null pointer.",
);
return false;
}
let elements = std::slice::from_raw_parts(elements as *const Id, size);
let gpo = &mut *(gpo as *mut T);
gpo.theory_atom_with_guard(
Id(atom_id_or_zero),
Id(term_id),
elements,
Id(operator_id),
Id(right_hand_side_id),
)
}
pub trait ToSymbol {
fn symbol(&self) -> Result<Symbol, ClingoError>;
}
impl ToSymbol for Symbol {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(*self)
}
}
impl ToSymbol for () {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Symbol::create_function("", &[], true)
}
}
impl<A: ToSymbol, B: ToSymbol> ToSymbol for (A, B) {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Symbol::create_function("", &[self.0.symbol()?, self.1.symbol()?], true)
}
}
impl<A: ToSymbol, B: ToSymbol, C: ToSymbol> ToSymbol for (A, B, C) {
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![self.0.symbol()?, self.1.symbol()?, self.2.symbol()?];
Symbol::create_function("", &tempvec, true)
}
}
impl<A: ToSymbol, B: ToSymbol, C: ToSymbol, D: ToSymbol> ToSymbol for (A, B, C, D) {
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<A: ToSymbol, B: ToSymbol, C: ToSymbol, D: ToSymbol, E: ToSymbol> ToSymbol for (A, B, C, D, E) {
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<A: ToSymbol, B: ToSymbol, C: ToSymbol, D: ToSymbol, E: ToSymbol, F: ToSymbol> ToSymbol
for (A, B, C, D, E, F)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<A: ToSymbol, B: ToSymbol, C: ToSymbol, D: ToSymbol, E: ToSymbol, F: ToSymbol, G: ToSymbol>
ToSymbol for (A, B, C, D, E, F, G)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<
A: ToSymbol,
B: ToSymbol,
C: ToSymbol,
D: ToSymbol,
E: ToSymbol,
F: ToSymbol,
G: ToSymbol,
H: ToSymbol,
> ToSymbol for (A, B, C, D, E, F, G, H)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
self.7.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<
A: ToSymbol,
B: ToSymbol,
C: ToSymbol,
D: ToSymbol,
E: ToSymbol,
F: ToSymbol,
G: ToSymbol,
H: ToSymbol,
I: ToSymbol,
> ToSymbol for (A, B, C, D, E, F, G, H, I)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
self.7.symbol()?,
self.8.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<
A: ToSymbol,
B: ToSymbol,
C: ToSymbol,
D: ToSymbol,
E: ToSymbol,
F: ToSymbol,
G: ToSymbol,
H: ToSymbol,
I: ToSymbol,
J: ToSymbol,
> ToSymbol for (A, B, C, D, E, F, G, H, I, J)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
self.7.symbol()?,
self.8.symbol()?,
self.9.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<
A: ToSymbol,
B: ToSymbol,
C: ToSymbol,
D: ToSymbol,
E: ToSymbol,
F: ToSymbol,
G: ToSymbol,
H: ToSymbol,
I: ToSymbol,
J: ToSymbol,
K: ToSymbol,
> ToSymbol for (A, B, C, D, E, F, G, H, I, J, K)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
self.7.symbol()?,
self.8.symbol()?,
self.9.symbol()?,
self.10.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl<
A: ToSymbol,
B: ToSymbol,
C: ToSymbol,
D: ToSymbol,
E: ToSymbol,
F: ToSymbol,
G: ToSymbol,
H: ToSymbol,
I: ToSymbol,
J: ToSymbol,
K: ToSymbol,
L: ToSymbol,
> ToSymbol for (A, B, C, D, E, F, G, H, I, J, K, L)
{
fn symbol(&self) -> Result<Symbol, ClingoError> {
let tempvec = vec![
self.0.symbol()?,
self.1.symbol()?,
self.2.symbol()?,
self.3.symbol()?,
self.4.symbol()?,
self.5.symbol()?,
self.6.symbol()?,
self.7.symbol()?,
self.8.symbol()?,
self.9.symbol()?,
self.10.symbol()?,
self.11.symbol()?,
];
Symbol::create_function("", &tempvec, true)
}
}
impl ToSymbol for bool {
fn symbol(&self) -> Result<Symbol, ClingoError> {
if *self {
Symbol::create_id("true", true)
} else {
Symbol::create_id("false", true)
}
}
}
impl ToSymbol for u8 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(i32::from(*self)))
}
}
impl ToSymbol for i8 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(i32::from(*self)))
}
}
impl ToSymbol for u16 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(i32::from(*self)))
}
}
impl ToSymbol for i16 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(i32::from(*self)))
}
}
impl ToSymbol for u32 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(*self as i32))
}
}
impl ToSymbol for i32 {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Ok(Symbol::create_number(*self))
}
}
impl ToSymbol for String {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Symbol::create_string(self)
}
}
impl ToSymbol for str {
fn symbol(&self) -> Result<Symbol, ClingoError> {
Symbol::create_string(self)
}
}
impl<T: ToSymbol> ToSymbol for &T {
fn symbol(&self) -> Result<Symbol, ClingoError> {
(*self).symbol()
}
}
pub trait FromSymbol: Sized {
type Error;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error>;
}
impl FromSymbol for Symbol {
type Error = Infallible;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
Ok(symbol)
}
}
impl FromSymbol for u8 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to u8"))
}
}
impl FromSymbol for i8 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to i8"))
}
}
impl FromSymbol for u16 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to u16"))
}
}
impl FromSymbol for i16 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to i16"))
}
}
impl FromSymbol for u32 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to u32"))
}
}
impl FromSymbol for i32 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol.number()
}
}
impl FromSymbol for u64 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to u64"))
}
}
impl FromSymbol for i64 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
Ok(symbol.number()? as i64)
}
}
impl FromSymbol for u128 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol
.number()?
.try_into()
.map_err(|_| ClingoError::new_external("Could not convert to u128"))
}
}
impl FromSymbol for i128 {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
Ok(symbol.number()? as i128)
}
}
impl FromSymbol for String {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
Ok(symbol.string()?.into())
}
}
impl FromSymbol for &'static str {
type Error = ClingoError;
fn from_symbol(symbol: Symbol) -> Result<Self, Self::Error> {
symbol.string()
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct FactBase {
facts: HashSet<Symbol>,
}
impl FactBase {
pub fn new() -> FactBase {
FactBase {
facts: HashSet::new(),
}
}
pub fn len(&self) -> usize {
self.facts.len()
}
pub fn is_empty(&self) -> bool {
self.facts.is_empty()
}
pub fn iter(&self) -> std::collections::hash_set::Iter<'_, Symbol> {
self.facts.iter()
}
pub fn insert(&mut self, fact: &dyn ToSymbol) {
self.facts.insert(fact.symbol().unwrap());
}
pub fn union(&mut self, facts: &FactBase) {
for s in &facts.facts {
self.facts.insert(*s);
}
}
pub fn print(&self) {
for fact in &self.facts {
print!("{fact}.");
}
println!();
}
}
#[cfg(feature = "derive")]
#[allow(unused_imports)]
pub use clingo_derive::*;
impl From<Symbol> for clingo_symbol_t {
fn from(symbol: Symbol) -> Self {
symbol.0
}
}
impl From<clingo_symbol_t> for Symbol {
fn from(symbol: clingo_symbol_t) -> Self {
Symbol(symbol)
}
}
impl From<Id> for clingo_id_t {
fn from(id: Id) -> Self {
id.0
}
}
impl From<Options> for clingo_options_t {
fn from(options: Options) -> Self {
options.0
}
}
impl From<&mut Options> for *mut clingo_options_t {
fn from(options: &mut Options) -> Self {
&mut options.0
}
}
impl From<Statistics> for clingo_statistic {
fn from(stats: Statistics) -> Self {
stats.0
}
}
impl From<&mut Statistics> for *mut clingo_statistic {
fn from(stats: &mut Statistics) -> Self {
&mut stats.0
}
}
impl From<Model> for clingo_model {
fn from(model: Model) -> Self {
model.0
}
}
impl From<&mut Model> for *mut clingo_model {
fn from(model: &mut Model) -> Self {
&mut model.0
}
}
impl<C: ControlCtx> From<GenericControl<C>> for NonNull<clingo_control> {
fn from(control: GenericControl<C>) -> Self {
control.ctl
}
}
impl<C: ControlCtx> From<&mut GenericControl<C>> for NonNull<clingo_control> {
fn from(control: &mut GenericControl<C>) -> Self {
control.ctl
}
}