use crate::ast::join_fmt_no_quote;
use biodivine_lib_bdd::{Bdd, BddVariableSet};
use core::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Default)]
#[derive(serde::Serialize, serde::Deserialize)]
pub struct SdfExpression(String);
impl fmt::Display for SdfExpression {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\"{}\"", self.0)
}
}
impl core::str::FromStr for SdfExpression {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(String::from_str(s)?))
}
}
crate::ast::impl_self_builder!(SdfExpression);
crate::ast::impl_simple!(SdfExpression);
impl SdfExpression {
#[expect(clippy::indexing_slicing, clippy::shadow_reuse)]
#[must_use]
#[inline]
pub fn new(bdd: &Bdd, variables: &BddVariableSet) -> Self {
use core::fmt::Write as _;
let mut s = "( ".to_owned();
_ = join_fmt_no_quote(
bdd.sat_clauses(),
&mut s,
|valuation, f| {
join_fmt_no_quote(
valuation.to_values().into_iter(),
f,
|(var, level), f| {
let name = variables.name_of(var);
if name.as_bytes()[0].is_ascii_digit() {
write!(f, "\\\"{name}\\\"")?;
} else {
write!(f, "{name}")?;
}
write!(f, " == 1'b{}", i8::from(level))
},
|f| write!(f, " && "),
)
},
|f| write!(f, ") || ( "),
);
s.push_str(" )");
Self(s)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::expression::BddBooleanExpression;
use std::str::FromStr as _;
#[test]
fn sdf() {
let variables = BddVariableSet::new(&["A", "B", "C", "D"]);
assert_eq!(
SdfExpression(
"( A == 1'b0 && B == 1'b1 && C == 1'b1) || ( A == 1'b1 && C == 1'b1 )".into()
),
SdfExpression::new(
&BddBooleanExpression::from_str("(A+B)*C").unwrap().bdd,
&variables
)
);
}
}