Lines
57.02 %
Functions
28.48 %
use super::errors::{ReprInstantiateError, ReprUpError};
use super::types::{LookupFn, ReprAssignment, ReprDeclLevel, ReprGetOrInitResult, ReprResult};
use crate::ast::{DeclarationPtr, DomainPtr, Expression, Literal, Name};
use crate::representation::ReprRule;
use conjure_cp_core::representation::ReprError;
use parking_lot::MappedRwLockReadGuard;
use serde::Deserialize;
use serde_json;
use std::any::Any;
use std::collections::{HashMap, VecDeque};
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
/// Detached representation structure for compact cost estimation.
/// Probing must neither modify the declaration nor commit uniform choices.
pub struct ReprStructureProbe {
pub domains: Vec<DomainPtr>,
pub constraints: Vec<Expression>,
}
pub trait ReprStateStored: Any + Send + Sync + Debug {
fn rule(&self) -> &'static dyn ReprRuleStored;
fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError>;
fn up(&self, raw_assignment: &HashMap<Name, Literal>) -> Result<Literal, ReprUpError> {
let lu: LookupFn<'_> =
Box::new(|decl: &DeclarationPtr| raw_assignment.get(&decl.name()).cloned());
self.up_via(&lu)
fn repr_vars(&self) -> VecDeque<DeclarationPtr>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn clone_box(&self) -> Box<dyn ReprStateStored>;
fn serialise(&self) -> Result<serde_json::Value, serde_json::Error>;
impl<D: ReprDeclLevel> ReprStateStored for D {
fn rule(&self) -> &'static dyn ReprRuleStored {
D::RULE
fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError> {
let res = self.lookup_via(lu)?;
Ok(res.up())
fn repr_vars(&self) -> VecDeque<DeclarationPtr> {
D::repr_vars(self)
fn as_any(&self) -> &dyn Any {
self
fn as_any_mut(&mut self) -> &mut dyn Any {
fn clone_box(&self) -> Box<dyn ReprStateStored> {
Box::new(self.clone())
fn serialise(&self) -> Result<serde_json::Value, serde_json::Error> {
serde_json::to_value(self)
pub trait ReprRuleStored: Send + Sync {
fn name(&self) -> &'static str;
fn short_name(&self) -> &'static str;
/// This representation's identity.
fn id(&self) -> super::ReprId;
/// Whether this representation is available when targeting `family`.
fn applies_to(&self, family: crate::settings::SolverFamily) -> bool;
fn is_integer_encoding(&self) -> bool;
fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult;
fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult;
/// Checks applicability without mutating the source declaration and returns its compactness
/// score.
fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError>;
fn probe_structure_for(&self, decl: &DeclarationPtr) -> Result<ReprStructureProbe, ReprError>;
fn get_or_init_for<'a>(
&self,
decl: &'a mut DeclarationPtr,
) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError>;
fn get_for<'a>(
decl: &'a DeclarationPtr,
) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>>;
fn deserialize_state(
val: serde_json::Value,
) -> Result<Box<dyn ReprStateStored>, serde_json::Error>;
impl<R: ReprRule> ReprRuleStored for R {
fn name(&self) -> &'static str {
R::NAME
fn id(&self) -> super::ReprId {
<R as ReprRule>::id()
fn short_name(&self) -> &'static str {
R::SHORT_NAME
fn applies_to(&self, family: crate::settings::SolverFamily) -> bool {
R::applies_to(family)
fn is_integer_encoding(&self) -> bool {
R::is_integer_encoding()
fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult {
R::init_for(decl)
fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult {
R::init_for_if_not_exists(decl)
fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError> {
let domain = R::domain_for(decl)?;
// Value lettings still need `down` to check that their value can be represented.
if (decl.as_find().is_some() || decl.is_find_auxiliary())
&& let Some(score) = R::probe_score(domain.clone())?
{
return Ok(score);
let mut detached = decl.clone().detach();
super::uniform::probe(|| {
R::init_for(&mut detached)?;
R::compactness_score(domain).map_err(Into::into)
})
fn probe_structure_for(&self, decl: &DeclarationPtr) -> Result<ReprStructureProbe, ReprError> {
R::domain_for(decl)?;
let (_, constraints) = R::init_for(&mut detached)?;
let state = R::get_for(&detached).expect("probe initialised representation");
let domains = ReprDeclLevel::repr_vars(&*state)
.iter()
.map(|var| {
var.domain()
.ok_or_else(|| ReprInstantiateError::NoDomain(var.clone()))
.collect::<Result<Vec<_>, _>>()?;
Ok(ReprStructureProbe {
domains,
constraints,
) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError> {
let (state, symbols, constraints) = R::get_or_init_for(decl)?;
let state_dyn = repr_state_as_dyn(state);
Ok((state_dyn, symbols, constraints))
) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>> {
let state = R::get_for(decl)?;
Some(repr_state_as_dyn(state))
) -> Result<Box<dyn ReprStateStored>, serde_json::Error> {
Ok(Box::new(R::DeclLevel::deserialize(val)?))
impl Debug for dyn ReprRuleStored {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(fmt, "ReprRule({})", self.name())
impl PartialEq for dyn ReprRuleStored {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
impl Eq for dyn ReprRuleStored {}
impl PartialOrd for dyn ReprRuleStored {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
impl Ord for dyn ReprRuleStored {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name().cmp(other.name())
impl Hash for dyn ReprRuleStored {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name().hash(state)
fn repr_state_as_dyn<'a, D>(
guard: MappedRwLockReadGuard<'a, D>,
) -> MappedRwLockReadGuard<'a, dyn ReprStateStored>
where
D: ReprStateStored,
MappedRwLockReadGuard::map(guard, |state| state as &dyn ReprStateStored)