use std::fmt::{self, Debug, Display, Formatter};
use pindakaas::Valuation as RawValuation;
use crate::{
IntVal,
actions::IntInspectionActions,
solver::{
Decision, View,
engine::State,
view::{boolean::BoolView, integer::IntView},
},
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum AnyView {
Bool(View<bool>),
Int(View<IntVal>),
}
#[derive(Clone, Copy)]
pub struct Solution<'a> {
pub(crate) sat: &'a dyn RawValuation,
pub(crate) state: &'a State,
}
pub trait Valuation {
type Val;
fn val(&self, sol: Solution<'_>) -> Self::Val;
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[expect(
variant_size_differences,
reason = "`Int` cannot be as small as `Bool`"
)]
pub enum Value {
Bool(bool),
Int(IntVal),
}
impl From<IntVal> for AnyView {
fn from(value: IntVal) -> Self {
AnyView::Int(View::from(value))
}
}
impl From<View<IntVal>> for AnyView {
fn from(value: View<IntVal>) -> Self {
AnyView::Int(value)
}
}
impl From<View<bool>> for AnyView {
fn from(value: View<bool>) -> Self {
AnyView::Bool(value)
}
}
impl Valuation for AnyView {
type Val = Value;
fn val(&self, sol: Solution<'_>) -> Value {
match self {
AnyView::Bool(view) => Value::Bool(view.val(sol)),
AnyView::Int(view) => Value::Int(Valuation::val(view, sol)),
}
}
}
impl Valuation for Decision<IntVal> {
type Val = IntVal;
fn val(&self, sol: Solution<'_>) -> IntVal {
debug_assert_eq!(
IntInspectionActions::min(self, sol.state),
IntInspectionActions::max(self, sol.state)
);
IntInspectionActions::min(self, sol.state)
}
}
impl Valuation for Decision<bool> {
type Val = bool;
fn val(&self, sol: Solution<'_>) -> bool {
sol.sat.value(self.0)
}
}
impl Debug for Solution<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let sat_str: *const dyn RawValuation = self.sat;
f.debug_struct("Solution")
.field("sat", &(sat_str as *const std::ffi::c_void))
.field("state", &self.state)
.finish()
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Value::Bool(b) => write!(f, "{}", b),
Value::Int(i) => write!(f, "{}", i),
}
}
}
impl From<IntVal> for Value {
fn from(value: IntVal) -> Self {
Value::Int(value)
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
impl Valuation for View<IntVal> {
type Val = IntVal;
fn val(&self, sol: Solution<'_>) -> IntVal {
match self.0 {
IntView::Const(c) => c,
IntView::Linear(v) => Valuation::val(&v, sol),
IntView::Bool(v) => Valuation::val(&v, sol),
}
}
}
impl Valuation for View<bool> {
type Val = bool;
fn val(&self, sol: Solution<'_>) -> bool {
match self.0 {
BoolView::Lit(decision) => decision.val(sol),
BoolView::Const(b) => b,
}
}
}