use std::collections::BTreeSet;
use std::fmt::Debug;
use std::fmt::Display;
use crate::Property;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AnfSet<P> {
negated: bool,
clauses: BTreeSet<Clause<P>>,
}
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
struct Clause<P> {
properties: BTreeSet<P>,
}
impl<P> AnfSet<P> {
pub fn empty() -> Self {
Self {
negated: false,
clauses: BTreeSet::new(),
}
}
pub fn universe() -> Self {
Self {
negated: true,
clauses: BTreeSet::new(),
}
}
}
impl<P> From<P> for AnfSet<P>
where
P: Ord,
{
fn from(property: P) -> Self {
let mut clauses = BTreeSet::new();
clauses.insert(property.into());
Self {
negated: false,
clauses,
}
}
}
impl<P> From<P> for Clause<P>
where
P: Ord,
{
fn from(property: P) -> Self {
let mut properties = BTreeSet::new();
properties.insert(property);
Self { properties }
}
}
impl<P> AnfSet<P> {
pub fn is_empty(&self) -> bool {
!self.negated && self.clauses.is_empty()
}
pub fn includes_universe(&self) -> bool {
self.negated
}
pub fn clauses(&self) -> impl Iterator<Item = impl Iterator<Item = &P>> + '_ {
self.clauses.iter().map(|c| c.properties.iter())
}
pub fn negate(&mut self) {
self.negated = !self.negated;
}
}
impl<P> AnfSet<P>
where
P: Property,
{
pub fn contains(&self, element: &P::Element) -> bool {
let mut result = self.negated;
for clause in &self.clauses {
result = result != clause.properties.iter().all(|p| p.is_satisfied(element))
}
result
}
}
impl<P> Debug for Clause<P>
where
P: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.properties.len() == 1 {
return write!(
f,
"Clause({:?})",
&self.properties.iter().next().expect("Inconsistent length")
);
}
let mut tuple = f.debug_tuple("Clause");
for property in &self.properties {
tuple.field(property);
}
tuple.finish()
}
}
impl<P> Display for AnfSet<P>
where
P: Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut first = true;
if self.negated {
first = false;
write!(f, "1")?;
}
for clause in &self.clauses {
if first {
first = false;
} else {
write!(f, " ⊕ ")?;
}
write!(f, "{}", clause)?;
}
if first {
write!(f, "∅")?;
}
Ok(())
}
}
impl<P> Display for Clause<P>
where
P: Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut first = true;
write!(f, "(")?;
for property in &self.properties {
if first {
first = false;
} else {
write!(f, " ∩ ")?;
}
write!(f, "{}", property)?;
}
write!(f, ")")?;
Ok(())
}
}
impl<P> std::ops::BitAnd for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
let lhs = self;
let mut result = AnfSet::empty();
result.negated = lhs.negated && rhs.negated;
if lhs.negated {
for rc in &rhs.clauses {
result.add_clause(rc.clone());
}
}
if rhs.negated {
for lc in &lhs.clauses {
result.add_clause(lc.clone());
}
}
for lc in &lhs.clauses {
for rc in &rhs.clauses {
if let Some(ic) = lc.intersection(rc) {
result.add_clause(ic);
}
}
}
result
}
}
impl<P> std::ops::BitAndAssign for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
fn bitand_assign(&mut self, rhs: Self) {
let lhs = std::mem::replace(self, AnfSet::empty());
*self = lhs & rhs;
}
}
impl<P> std::ops::BitOr for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
let lhs = self;
let mut result = AnfSet::empty();
result.negated = lhs.negated || rhs.negated;
result.clauses = lhs.clauses.clone();
for rc in &rhs.clauses {
result.add_clause(rc.clone());
}
if lhs.negated {
for rc in &rhs.clauses {
result.add_clause(rc.clone());
}
}
if rhs.negated {
for lc in &lhs.clauses {
result.add_clause(lc.clone());
}
}
for lc in &lhs.clauses {
for rc in &rhs.clauses {
if let Some(ic) = lc.intersection(rc) {
result.add_clause(ic);
}
}
}
result
}
}
impl<P> std::ops::BitOrAssign for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
fn bitor_assign(&mut self, rhs: Self) {
let lhs = std::mem::replace(self, AnfSet::empty());
*self = lhs | rhs;
}
}
impl<P> std::ops::BitXor for AnfSet<P>
where
P: Eq + Ord + Simplifiable,
{
type Output = Self;
fn bitxor(mut self, rhs: Self) -> Self::Output {
self ^= rhs;
self
}
}
impl<P> std::ops::BitXorAssign for AnfSet<P>
where
P: Eq + Ord + Simplifiable,
{
fn bitxor_assign(&mut self, rhs: Self) {
self.negated = self.negated != rhs.negated;
for rc in rhs.clauses {
self.add_clause(rc);
}
}
}
impl<P> std::ops::Not for AnfSet<P> {
type Output = Self;
fn not(mut self) -> Self::Output {
self.negated = !self.negated;
self
}
}
impl<P> std::ops::Sub for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
self & !other
}
}
impl<P> std::ops::SubAssign for AnfSet<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
fn sub_assign(&mut self, other: Self) {
*self &= !other;
}
}
impl<P> AnfSet<P>
where
P: Eq + Ord + Simplifiable,
{
fn add_clause(&mut self, mut clause: Clause<P>) {
let prev = std::mem::take(&mut self.clauses);
let mut clauses = prev.into_iter();
while let Some(lc) = clauses.next() {
match lc.symmetric_difference(clause) {
Simplification::Remove => {
self.clauses.extend(clauses);
return;
}
Simplification::Keep(lc, c) => {
self.clauses.insert(lc);
clause = c;
}
Simplification::Replace(c) => {
clause = c;
}
}
}
self.clauses.insert(clause);
}
}
impl<P> Clause<P>
where
P: Eq + Ord + Simplifiable,
{
fn symmetric_difference(mut self, mut other: Clause<P>) -> Simplification<Clause<P>> {
if self.properties == other.properties {
return Simplification::Remove;
}
if self.properties.len() == 1 && other.properties.len() == 1 {
let lp = self
.properties
.pop_first()
.expect("Properties has length 1");
let rp = other
.properties
.pop_first()
.expect("Properties has length 1");
return lp.symmetric_difference(rp).into();
}
Simplification::Keep(self, other)
}
fn add_property(&mut self, mut property: P) -> Option<()> {
let prev = std::mem::take(&mut self.properties);
let properties = prev.into_iter();
for lp in properties {
match lp.intersection(property) {
Simplification::Remove => {
return None;
}
Simplification::Keep(lp, p) => {
self.properties.insert(lp);
property = p;
}
Simplification::Replace(p) => {
property = p;
}
}
}
self.properties.insert(property);
Some(())
}
}
impl<P> Clause<P>
where
P: Clone + Eq + Ord + Simplifiable,
{
fn intersection(&self, other: &Clause<P>) -> Option<Clause<P>> {
let mut result = self.clone();
for rp in &other.properties {
result.add_property(rp.clone())?;
}
Some(result)
}
}
pub trait Simplifiable: Sized {
fn intersection(self, other: Self) -> Simplification<Self>;
fn symmetric_difference(self, other: Self) -> Simplification<Self>;
}
pub enum Simplification<P> {
Remove,
Keep(P, P),
Replace(P),
}
impl<P> From<Simplification<P>> for Simplification<Clause<P>>
where
P: Ord,
{
fn from(p: Simplification<P>) -> Self {
match p {
Simplification::Remove => Simplification::Remove,
Simplification::Keep(f1, f2) => Simplification::Keep(f1.into(), f2.into()),
Simplification::Replace(f) => Simplification::Replace(f.into()),
}
}
}