use crate::biodivine_std::bitvector::{ArrayBitVector, BitVector};
use crate::biodivine_std::traits::Set;
use crate::symbolic_async_graph::bdd_set::BddSet;
use crate::symbolic_async_graph::projected_iteration::{RawProjection, StateProjection};
use crate::symbolic_async_graph::{GraphVertexIterator, GraphVertices, SymbolicContext};
use crate::trap_spaces::{NetworkSpaces, SymbolicSpaceContext};
use crate::VariableId;
use biodivine_lib_bdd::{Bdd, BddVariable};
use num_bigint::BigInt;
use std::convert::TryFrom;
impl GraphVertices {
pub fn new(bdd: Bdd, context: &SymbolicContext) -> Self {
GraphVertices {
bdd,
state_variables: context.state_variables.clone(),
}
}
pub fn copy(&self, bdd: Bdd) -> Self {
GraphVertices {
bdd,
state_variables: self.state_variables.clone(),
}
}
pub fn into_bdd(self) -> Bdd {
self.bdd
}
pub fn as_bdd(&self) -> &Bdd {
&self.bdd
}
pub fn approx_cardinality(&self) -> f64 {
BddSet::approx_cardinality(self)
}
pub fn exact_cardinality(&self) -> BigInt {
BddSet::exact_cardinality(self)
}
pub fn pick_singleton(&self) -> GraphVertices {
if self.is_empty() {
self.clone()
} else {
let witness = self.bdd.sat_witness().unwrap();
let partial_valuation: Vec<(BddVariable, bool)> = self
.state_variables
.iter()
.map(|v| (*v, witness[*v]))
.collect();
self.copy(self.bdd.select(&partial_valuation))
}
}
#[allow(deprecated)]
pub fn materialize(&self) -> crate::symbolic_async_graph::IterableVertices {
crate::symbolic_async_graph::IterableVertices {
projection: RawProjection::new(self.state_variables.clone(), self.as_bdd()),
state_variables: self.state_variables.clone(),
}
}
pub fn symbolic_size(&self) -> usize {
BddSet::symbolic_size(self)
}
pub fn to_dot_string(&self, context: &SymbolicContext) -> String {
self.bdd.to_dot_string(&context.bdd, true)
}
pub fn is_subspace(&self) -> bool {
self.bdd.is_clause()
}
pub fn is_singleton(&self) -> bool {
if self.bdd.is_clause() {
let clause = self.bdd.first_clause().unwrap();
for var in &self.state_variables {
if clause.get_value(*var).is_none() {
return false;
}
}
true
} else {
false
}
}
pub fn restrict_network_variable(&self, variable: VariableId, value: bool) -> Self {
let var = self.state_variables[variable.0];
self.copy(self.bdd.var_restrict(var, value))
}
pub fn fix_network_variable(&self, variable: VariableId, value: bool) -> Self {
let var = self.state_variables[variable.0];
self.copy(self.bdd.var_select(var, value))
}
pub fn raw_projection(&self, eliminate: &[BddVariable]) -> RawProjection {
let mut retained = Vec::new();
for v in &self.state_variables {
if !eliminate.contains(v) {
retained.push(*v);
}
}
RawProjection::new(retained, &self.bdd)
}
pub fn state_projection(&self, variables: &[VariableId]) -> StateProjection {
StateProjection::new(variables.to_vec(), &self.state_variables, &self.bdd)
}
pub fn iter(&self) -> GraphVertexIterator {
let projection = RawProjection::new(self.state_variables.clone(), &self.bdd);
GraphVertexIterator {
inner_iterator: projection.into_iter(),
state_variables: self.state_variables.clone(),
}
}
pub fn to_singleton_spaces(&self, ctx: &SymbolicSpaceContext) -> NetworkSpaces {
NetworkSpaces::new(ctx.vertices_to_spaces(self.as_bdd()), ctx)
}
}
impl IntoIterator for GraphVertices {
type Item = ArrayBitVector;
type IntoIter = GraphVertexIterator;
fn into_iter(self) -> Self::IntoIter {
let projection = RawProjection::new(self.state_variables.clone(), &self.bdd);
GraphVertexIterator {
inner_iterator: projection.into_iter(),
state_variables: self.state_variables,
}
}
}
#[allow(deprecated)]
impl crate::symbolic_async_graph::IterableVertices {
pub fn iter(&self) -> GraphVertexIterator {
GraphVertexIterator {
inner_iterator: self.projection.clone().into_iter(),
state_variables: self.state_variables.clone(),
}
}
}
impl Iterator for GraphVertexIterator {
type Item = ArrayBitVector;
fn next(&mut self) -> Option<Self::Item> {
if let Some(valuation) = self.inner_iterator.next() {
let mut state = ArrayBitVector::empty(self.state_variables.len());
for (i, v) in self.state_variables.iter().enumerate() {
state.set(i, valuation[*v].unwrap());
}
Some(state)
} else {
None
}
}
}
impl BddSet for GraphVertices {
fn as_bdd(&self) -> &Bdd {
GraphVertices::as_bdd(self)
}
fn copy(&self, bdd: Bdd) -> Self {
GraphVertices::copy(self, bdd)
}
fn active_variables(&self) -> u16 {
u16::try_from(self.state_variables.len()).unwrap()
}
}