1use crate::literal::{Literal, Polarity, Variable};
3use bitvec::prelude::*;
4use std::fmt::Display;
5use tabled::{builder::Builder, grid::config::HorizontalLine, settings::Theme};
6
7#[derive(Debug, PartialEq)]
9pub struct Models {
10 models: Vec<BitVec>,
11 variables: Vec<Variable>,
12}
13
14impl Models {
15 pub(crate) fn new(models: &[BitVec], variables: Vec<Variable>) -> Self {
16 let mut models = models.to_owned();
17 models.sort();
18 Models { models, variables }
19 }
20
21 #[must_use]
23 pub fn all_models(&self) -> Vec<Model> {
24 self.models
25 .iter()
26 .map(|enumeration_bitvec| {
27 Model::new_from_bitvector(enumeration_bitvec, &self.variables)
28 })
29 .collect()
30 }
31}
32
33impl Display for Models {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 let mut builder = Builder::default();
36 builder.push_record(self.variables.iter().map(Variable::label));
37
38 for model in &self.models {
39 builder.push_record(
40 model
41 .iter()
42 .map(|assignment| if *assignment { "1" } else { "0" }),
43 );
44 }
45
46 let mut style = Theme::default();
47 style.insert_horizontal_line(1, HorizontalLine::full('-', '-', ' ', ' '));
48 let output = builder.build().with(style).to_string();
49 write!(f, "{output}")
50 }
51}
52
53#[derive(Debug, PartialEq, Eq)]
56pub struct Model {
57 literals: Vec<Literal>,
58}
59
60impl Model {
61 #[allow(unused)]
62 pub(crate) fn new_from_literals(literals: &[Literal]) -> Self {
63 let mut literals = literals.to_owned();
64 literals.sort();
65 Model { literals }
66 }
67
68 fn new_from_bitvector(model: &BitVec, labels: &[Variable]) -> Self {
69 Model {
70 literals: model
71 .iter()
72 .zip(labels.iter())
73 .map(|(polarity, var_label)| {
74 Literal::new_with_label(Polarity::from(*polarity), var_label.clone())
75 })
76 .collect(),
77 }
78 }
79}
80
81impl Display for Model {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 fn lit_repr(literal: &Literal) -> String {
84 format!(
85 "{}{literal}",
86 if literal.polarity() == Polarity::Negative {
87 ""
88 } else {
89 " "
90 }
91 )
92 }
93
94 write!(
95 f,
96 "{{{}}}",
97 self.literals
98 .iter()
99 .map(lit_repr)
100 .collect::<Vec<String>>()
101 .join(", ")
102 )
103 }
104}