1
use super::errors::{ReprInstantiateError, ReprUpError};
2
use super::types::{LookupFn, ReprAssignment, ReprDeclLevel, ReprGetOrInitResult, ReprResult};
3
use crate::ast::{DeclarationPtr, DomainPtr, Expression, Literal, Name};
4
use crate::representation::ReprRule;
5
use conjure_cp_core::representation::ReprError;
6
use parking_lot::MappedRwLockReadGuard;
7
use serde::Deserialize;
8
use serde_json;
9
use std::any::Any;
10
use std::collections::{HashMap, VecDeque};
11
use std::fmt::Debug;
12
use std::hash::{Hash, Hasher};
13

            
14
/// Detached representation structure for compact cost estimation.
15
/// Probing must neither modify the declaration nor commit uniform choices.
16
pub struct ReprStructureProbe {
17
    pub domains: Vec<DomainPtr>,
18
    pub constraints: Vec<Expression>,
19
}
20

            
21
pub 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

            
43
impl<D: ReprDeclLevel> ReprStateStored for D {
44
3996885
    fn rule(&self) -> &'static dyn ReprRuleStored {
45
3996885
        D::RULE
46
3996885
    }
47

            
48
15097933
    fn up_via(&self, lu: &LookupFn<'_>) -> Result<Literal, ReprUpError> {
49
15097933
        let res = self.lookup_via(lu)?;
50
15087013
        Ok(res.up())
51
15097933
    }
52

            
53
    fn repr_vars(&self) -> VecDeque<DeclarationPtr> {
54
        D::repr_vars(self)
55
    }
56

            
57
9692492
    fn as_any(&self) -> &dyn Any {
58
9692492
        self
59
9692492
    }
60

            
61
    fn as_any_mut(&mut self) -> &mut dyn Any {
62
        self
63
    }
64

            
65
8
    fn clone_box(&self) -> Box<dyn ReprStateStored> {
66
8
        Box::new(self.clone())
67
8
    }
68

            
69
    fn serialise(&self) -> Result<serde_json::Value, serde_json::Error> {
70
        serde_json::to_value(self)
71
    }
72
}
73

            
74
pub 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

            
113
impl<R: ReprRule> ReprRuleStored for R {
114
72951074
    fn name(&self) -> &'static str {
115
72951074
        R::NAME
116
72951074
    }
117

            
118
181112760
    fn id(&self) -> super::ReprId {
119
181112760
        <R as ReprRule>::id()
120
181112760
    }
121

            
122
117016
    fn short_name(&self) -> &'static str {
123
117016
        R::SHORT_NAME
124
117016
    }
125

            
126
2842
    fn applies_to(&self, family: crate::settings::SolverFamily) -> bool {
127
2842
        R::applies_to(family)
128
2842
    }
129

            
130
59685637
    fn is_integer_encoding(&self) -> bool {
131
59685637
        R::is_integer_encoding()
132
59685637
    }
133

            
134
578592
    fn init_for(&self, decl: &mut DeclarationPtr) -> ReprResult {
135
578592
        R::init_for(decl)
136
578592
    }
137

            
138
4244386
    fn init_for_if_not_exists(&self, decl: &mut DeclarationPtr) -> ReprResult {
139
4244386
        R::init_for_if_not_exists(decl)
140
4244386
    }
141

            
142
46769441
    fn probe_for(&self, decl: &DeclarationPtr) -> Result<usize, ReprError> {
143
46769441
        let domain = R::domain_for(decl)?;
144
        // Value lettings still need `down` to check that their value can be represented.
145
18220342
        if (decl.as_find().is_some() || decl.is_find_auxiliary())
146
18185356
            && let Some(score) = R::probe_score(domain.clone())?
147
        {
148
1005527
            return Ok(score);
149
16776702
        }
150
16776702
        let mut detached = decl.clone().detach();
151
16776702
        super::uniform::probe(|| {
152
16776702
            R::init_for(&mut detached)?;
153
1952115
            R::compactness_score(domain).map_err(Into::into)
154
16776702
        })
155
46769441
    }
156

            
157
679
    fn probe_structure_for(&self, decl: &DeclarationPtr) -> Result<ReprStructureProbe, ReprError> {
158
679
        R::domain_for(decl)?;
159
679
        let mut detached = decl.clone().detach();
160
679
        super::uniform::probe(|| {
161
679
            let (_, constraints) = R::init_for(&mut detached)?;
162
679
            let state = R::get_for(&detached).expect("probe initialised representation");
163
679
            let domains = ReprDeclLevel::repr_vars(&*state)
164
679
                .iter()
165
1763
                .map(|var| {
166
1763
                    var.domain()
167
                        .ok_or_else(|| ReprInstantiateError::NoDomain(var.clone()))
168
1763
                })
169
                .collect::<Result<Vec<_>, _>>()?;
170
679
            Ok(ReprStructureProbe {
171
679
                domains,
172
679
                constraints,
173
679
            })
174
679
        })
175
679
    }
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

            
202
impl 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

            
208
impl PartialEq for dyn ReprRuleStored {
209
257328373
    fn eq(&self, other: &Self) -> bool {
210
257328373
        self.id() == other.id()
211
257328373
    }
212
}
213

            
214
impl Eq for dyn ReprRuleStored {}
215

            
216
impl PartialOrd for dyn ReprRuleStored {
217
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
218
        Some(self.cmp(other))
219
    }
220
}
221

            
222
impl Ord for dyn ReprRuleStored {
223
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
224
        self.name().cmp(other.name())
225
    }
226
}
227

            
228
impl Hash for dyn ReprRuleStored {
229
135515
    fn hash<H: Hasher>(&self, state: &mut H) {
230
135515
        self.name().hash(state)
231
135515
    }
232
}
233

            
234
fn repr_state_as_dyn<'a, D>(
235
    guard: MappedRwLockReadGuard<'a, D>,
236
) -> MappedRwLockReadGuard<'a, dyn ReprStateStored>
237
where
238
    D: ReprStateStored,
239
{
240
    MappedRwLockReadGuard::map(guard, |state| state as &dyn ReprStateStored)
241
}