conjure_cp_core/representation/
stored.rs1use 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
14pub 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 fn id(&self) -> super::ReprId;
81
82 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 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 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}