Skip to main content

conjure_cp_core/representation/
stored.rs

1use super::errors::{ReprInstantiateError, ReprUpError};
2use super::types::{LookupFn, ReprAssignment, ReprDeclLevel, ReprGetOrInitResult, ReprResult};
3use crate::ast::{DeclarationPtr, DomainPtr, Expression, Literal, Name};
4use crate::representation::ReprRule;
5use conjure_cp_core::representation::ReprError;
6use parking_lot::MappedRwLockReadGuard;
7use serde::Deserialize;
8use serde_json;
9use std::any::Any;
10use std::collections::{HashMap, VecDeque};
11use std::fmt::Debug;
12use std::hash::{Hash, Hasher};
13
14/// Detached representation structure for compact cost estimation.
15/// Probing must neither modify the declaration nor commit uniform choices.
16pub struct ReprStructureProbe {
17    pub domains: Vec<DomainPtr>,
18    pub constraints: Vec<Expression>,
19}
20
21pub trait ReprStateStored: Any + Send + Sync + Debug {
22    fn rule(&self) -> &'static dyn ReprRuleStored;
23
24    fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError>;
25
26    fn up(&self, raw_assignment: &HashMap<Name, Literal>) -> Result<Literal, ReprUpError> {
27        let lu: LookupFn<'_> =
28            Box::new(|decl: &DeclarationPtr| raw_assignment.get(&decl.name()).cloned());
29        self.up_via(&lu)
30    }
31
32    fn repr_vars(&self) -> VecDeque<DeclarationPtr>;
33
34    fn as_any(&self) -> &dyn Any;
35
36    fn as_any_mut(&mut self) -> &mut dyn Any;
37
38    fn clone_box(&self) -> Box<dyn ReprStateStored>;
39
40    fn serialise(&self) -> Result<serde_json::Value, serde_json::Error>;
41}
42
43impl<D: ReprDeclLevel> ReprStateStored for D {
44    fn rule(&self) -> &'static dyn ReprRuleStored {
45        D::RULE
46    }
47
48    fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError> {
49        let res = self.lookup_via(lu)?;
50        Ok(res.up())
51    }
52
53    fn repr_vars(&self) -> VecDeque<DeclarationPtr> {
54        D::repr_vars(self)
55    }
56
57    fn as_any(&self) -> &dyn Any {
58        self
59    }
60
61    fn as_any_mut(&mut self) -> &mut dyn Any {
62        self
63    }
64
65    fn clone_box(&self) -> Box<dyn ReprStateStored> {
66        Box::new(self.clone())
67    }
68
69    fn serialise(&self) -> Result<serde_json::Value, serde_json::Error> {
70        serde_json::to_value(self)
71    }
72}
73
74pub trait ReprRuleStored: Send + Sync {
75    fn name(&self) -> &'static str;
76
77    fn short_name(&self) -> &'static str;
78
79    /// This representation's identity.
80    fn id(&self) -> super::ReprId;
81
82    /// Whether this representation is available when targeting `family`.
83    fn applies_to(&self, family: crate::settings::SolverFamily) -> bool;
84
85    fn is_integer_encoding(&self) -> bool;
86
87    fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult;
88
89    fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult;
90
91    /// Checks applicability without mutating the source declaration and returns its compactness
92    /// score.
93    fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError>;
94
95    fn probe_structure_for(&self, decl: &DeclarationPtr) -> Result<ReprStructureProbe, ReprError>;
96
97    fn get_or_init_for<'a>(
98        &self,
99        decl: &'a mut DeclarationPtr,
100    ) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError>;
101
102    fn get_for<'a>(
103        &self,
104        decl: &'a DeclarationPtr,
105    ) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>>;
106
107    fn deserialize_state(
108        &self,
109        val: serde_json::Value,
110    ) -> Result<Box<dyn ReprStateStored>, serde_json::Error>;
111}
112
113impl<R: ReprRule> ReprRuleStored for R {
114    fn name(&self) -> &'static str {
115        R::NAME
116    }
117
118    fn id(&self) -> super::ReprId {
119        <R as ReprRule>::id()
120    }
121
122    fn short_name(&self) -> &'static str {
123        R::SHORT_NAME
124    }
125
126    fn applies_to(&self, family: crate::settings::SolverFamily) -> bool {
127        R::applies_to(family)
128    }
129
130    fn is_integer_encoding(&self) -> bool {
131        R::is_integer_encoding()
132    }
133
134    fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult {
135        R::init_for(decl)
136    }
137
138    fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult {
139        R::init_for_if_not_exists(decl)
140    }
141
142    fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError> {
143        let domain = R::domain_for(decl)?;
144        // Value lettings still need `down` to check that their value can be represented.
145        if (decl.as_find().is_some() || decl.is_find_auxiliary())
146            && let Some(score) = R::probe_score(domain.clone())?
147        {
148            return Ok(score);
149        }
150        let mut detached = decl.clone().detach();
151        super::uniform::probe(|| {
152            R::init_for(&mut detached)?;
153            R::compactness_score(domain).map_err(Into::into)
154        })
155    }
156
157    fn probe_structure_for(&self, decl: &DeclarationPtr) -> Result<ReprStructureProbe, ReprError> {
158        R::domain_for(decl)?;
159        let mut detached = decl.clone().detach();
160        super::uniform::probe(|| {
161            let (_, constraints) = R::init_for(&mut detached)?;
162            let state = R::get_for(&detached).expect("probe initialised representation");
163            let domains = ReprDeclLevel::repr_vars(&*state)
164                .iter()
165                .map(|var| {
166                    var.domain()
167                        .ok_or_else(|| ReprInstantiateError::NoDomain(var.clone()))
168                })
169                .collect::<Result<Vec<_>, _>>()?;
170            Ok(ReprStructureProbe {
171                domains,
172                constraints,
173            })
174        })
175    }
176
177    fn get_or_init_for<'a>(
178        &self,
179        decl: &'a mut DeclarationPtr,
180    ) -> ReprGetOrInitResult<'a, dyn ReprStateStored, ReprError> {
181        let (state, symbols, constraints) = R::get_or_init_for(decl)?;
182        let state_dyn = repr_state_as_dyn(state);
183        Ok((state_dyn, symbols, constraints))
184    }
185
186    fn get_for<'a>(
187        &self,
188        decl: &'a DeclarationPtr,
189    ) -> Option<MappedRwLockReadGuard<'a, dyn ReprStateStored>> {
190        let state = R::get_for(decl)?;
191        Some(repr_state_as_dyn(state))
192    }
193
194    fn deserialize_state(
195        &self,
196        val: serde_json::Value,
197    ) -> Result<Box<dyn ReprStateStored>, serde_json::Error> {
198        Ok(Box::new(R::DeclLevel::deserialize(val)?))
199    }
200}
201
202impl Debug for dyn ReprRuleStored {
203    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
204        write!(fmt, "ReprRule({})", self.name())
205    }
206}
207
208impl PartialEq for dyn ReprRuleStored {
209    fn eq(&self, other: &Self) -> bool {
210        self.id() == other.id()
211    }
212}
213
214impl Eq for dyn ReprRuleStored {}
215
216impl PartialOrd for dyn ReprRuleStored {
217    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
218        Some(self.cmp(other))
219    }
220}
221
222impl Ord for dyn ReprRuleStored {
223    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
224        self.name().cmp(other.name())
225    }
226}
227
228impl Hash for dyn ReprRuleStored {
229    fn hash<H: Hasher>(&self, state: &mut H) {
230        self.name().hash(state)
231    }
232}
233
234fn repr_state_as_dyn<'a, D>(
235    guard: MappedRwLockReadGuard<'a, D>,
236) -> MappedRwLockReadGuard<'a, dyn ReprStateStored>
237where
238    D: ReprStateStored,
239{
240    MappedRwLockReadGuard::map(guard, |state| state as &dyn ReprStateStored)
241}