oxiz_solver/model/
builder.rs1use oxiz_sat::Lit;
18use rustc_hash::FxHashMap;
19
20pub type VarId = u32;
22
23pub type SortId = u32;
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum Value {
29 Bool(bool),
31 Int(i64),
33 Rational(i64, i64),
35 BitVec(u64, u32),
37 Uninterpreted(String),
39}
40
41#[derive(Debug, Clone)]
43pub struct Model {
44 pub bool_assignments: FxHashMap<Lit, bool>,
46 pub theory_assignments: FxHashMap<VarId, Value>,
48}
49
50impl Model {
51 pub fn new() -> Self {
53 Self {
54 bool_assignments: FxHashMap::default(),
55 theory_assignments: FxHashMap::default(),
56 }
57 }
58
59 pub fn assign_bool(&mut self, lit: Lit, value: bool) {
61 self.bool_assignments.insert(lit, value);
62 }
63
64 pub fn assign_theory(&mut self, var: VarId, value: Value) {
66 self.theory_assignments.insert(var, value);
67 }
68
69 pub fn get_bool(&self, lit: Lit) -> Option<bool> {
71 self.bool_assignments.get(&lit).copied()
72 }
73
74 pub fn get_theory(&self, var: VarId) -> Option<&Value> {
76 self.theory_assignments.get(&var)
77 }
78}
79
80impl Default for Model {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86#[derive(Debug, Clone)]
88pub struct ModelBuilderConfig {
89 pub minimize: bool,
91 pub complete: bool,
93 pub default_int: i64,
95}
96
97impl Default for ModelBuilderConfig {
98 fn default() -> Self {
99 Self {
100 minimize: false,
101 complete: true,
102 default_int: 0,
103 }
104 }
105}
106
107#[derive(Debug, Clone, Default)]
109pub struct ModelBuilderStats {
110 pub models_built: u64,
112 pub vars_assigned: u64,
114 pub minimizations: u64,
116}
117
118pub struct ModelBuilder {
120 config: ModelBuilderConfig,
121 stats: ModelBuilderStats,
122}
123
124impl ModelBuilder {
125 pub fn new() -> Self {
127 Self::with_config(ModelBuilderConfig::default())
128 }
129
130 pub fn with_config(config: ModelBuilderConfig) -> Self {
132 Self {
133 config,
134 stats: ModelBuilderStats::default(),
135 }
136 }
137
138 pub fn stats(&self) -> &ModelBuilderStats {
140 &self.stats
141 }
142
143 pub fn build_model(
145 &mut self,
146 bool_assignment: &FxHashMap<Lit, bool>,
147 theory_models: Vec<FxHashMap<VarId, Value>>,
148 ) -> Model {
149 self.stats.models_built += 1;
150
151 let mut model = Model::new();
152
153 for (&lit, &value) in bool_assignment {
155 model.assign_bool(lit, value);
156 self.stats.vars_assigned += 1;
157 }
158
159 for theory_model in theory_models {
161 for (var, value) in theory_model {
162 if let Some(existing) = model.get_theory(var)
164 && existing != &value
165 {
166 continue;
168 }
169
170 model.assign_theory(var, value);
171 self.stats.vars_assigned += 1;
172 }
173 }
174
175 if self.config.complete {
177 self.complete_model(&mut model);
178 }
179
180 if self.config.minimize {
182 self.minimize_model(&mut model);
183 }
184
185 model
186 }
187
188 fn complete_model(&mut self, _model: &mut Model) {
190 }
193
194 fn minimize_model(&mut self, _model: &mut Model) {
196 self.stats.minimizations += 1;
197 }
200
201 pub fn validate(&self, _model: &Model) -> bool {
203 true
206 }
207}
208
209impl Default for ModelBuilder {
210 fn default() -> Self {
211 Self::new()
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218
219 #[test]
220 fn test_model_creation() {
221 let model = Model::new();
222 assert!(model.bool_assignments.is_empty());
223 assert!(model.theory_assignments.is_empty());
224 }
225
226 #[test]
227 fn test_bool_assignment() {
228 let mut model = Model::new();
229 let lit = Lit::from_dimacs(1);
230
231 model.assign_bool(lit, true);
232
233 assert_eq!(model.get_bool(lit), Some(true));
234 }
235
236 #[test]
237 fn test_theory_assignment() {
238 let mut model = Model::new();
239
240 model.assign_theory(0, Value::Int(42));
241
242 assert_eq!(model.get_theory(0), Some(&Value::Int(42)));
243 }
244
245 #[test]
246 fn test_builder_creation() {
247 let builder = ModelBuilder::new();
248 assert_eq!(builder.stats().models_built, 0);
249 }
250
251 #[test]
252 fn test_build_model() {
253 let mut builder = ModelBuilder::new();
254
255 let bool_map = FxHashMap::default();
256 let theory_models = vec![{
257 let mut m = FxHashMap::default();
258 m.insert(0, Value::Int(5));
259 m
260 }];
261
262 let model = builder.build_model(&bool_map, theory_models);
263
264 assert_eq!(model.get_theory(0), Some(&Value::Int(5)));
265 assert_eq!(builder.stats().models_built, 1);
266 }
267
268 #[test]
269 fn test_validate() {
270 let builder = ModelBuilder::new();
271 let model = Model::new();
272
273 assert!(builder.validate(&model));
274 }
275
276 #[test]
277 fn test_value_types() {
278 let mut model = Model::new();
279
280 model.assign_theory(0, Value::Bool(true));
281 model.assign_theory(1, Value::Int(42));
282 model.assign_theory(2, Value::Rational(3, 4));
283 model.assign_theory(3, Value::BitVec(0xFF, 8));
284
285 assert_eq!(model.get_theory(0), Some(&Value::Bool(true)));
286 assert_eq!(model.get_theory(1), Some(&Value::Int(42)));
287 assert_eq!(model.get_theory(2), Some(&Value::Rational(3, 4)));
288 assert_eq!(model.get_theory(3), Some(&Value::BitVec(0xFF, 8)));
289 }
290}