1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Useful traits for constraint systems that define the interface required for planning.

use crate::{builders::method_builder::MutabilityMismatch, planner::Vertex};
use std::{
    fmt::{Debug, Display},
    ops::{Index, IndexMut},
    sync::Arc,
};

/// The potential errors from performing a method call.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum MethodFailure {
    /// An attempt to use a variable that does not exist.
    NoSuchVariable(String),
    /// The constraint satisfaction method received too few or too many values as input.
    WrongInputCount(usize, usize),
    /// The constraint satisfaction method returned too few or too many values as output.
    WrongOutputCount(usize, usize),
    /// Unexpected mutability of an argument.
    MutabilityMismatch(MutabilityMismatch),
    /// Failure to convert a variable into the specified type.
    TypeConversionFailure(&'static str, &'static str),
    /// A custom error from the programmer.
    Custom(String),
}

/// The result of calling a method's function.
pub type MethodResult<T> = Result<Vec<T>, MethodFailure>;

/// The function contained within a method.
pub type MethodFunction<T> = Arc<dyn Fn(Vec<Arc<T>>) -> MethodResult<Arc<T>> + Send + Sync>;

/// An extension of the [`Vertex`] trait for methods.
pub trait MethodSpec: Vertex {
    /// The input and output type of the method.
    type Arg;
    /// Constructs a new [`MethodSpec`] with the specified name, inputs, outputs, and function.
    fn new(
        name: String,
        inputs: Vec<usize>,
        outputs: Vec<usize>,
        apply: MethodFunction<Self::Arg>,
    ) -> Self;
    /// Applies the provided arguments to the inner function of the method.
    fn apply(&self, args: Vec<Arc<Self::Arg>>) -> MethodResult<Arc<Self::Arg>>;
    /// Returns a reference to the name of the method.
    fn name(&self) -> &str;
}

/// A trait for objects that can act as
/// constraints in a constraint system.
pub trait ConstraintSpec {
    /// The type of the methods of the constraint.
    type Method: MethodSpec;
    /// Constructs a new constraint with the provided methods.
    fn new(methods: Vec<Self::Method>) -> Self;
    /// Returns a reference to the name of the constraint.
    fn name(&self) -> &str;
    /// Returns a slice to the methods of the constraint.
    fn methods(&self) -> &[Self::Method];
    /// Adds a new method to the constraint.
    fn add_method(&mut self, m: Self::Method);
    /// Removes a method from the constraint.
    fn remove_method(&mut self, name: &str);
    /// Returns a slice to the variables used by the methods of the constraint.
    fn variables(&self) -> &[usize];
    /// Whether or not this constraint is active.
    fn is_active(&self) -> bool;
}

/// Errors that can occur during planning.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PlanError {
    /// The system was overconstrained, and no plan was found.
    Overconstrained,
}

impl Display for PlanError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "No valid plan was found since the system is overconstrained"
        )
    }
}

/// A trait for objects which have the properties of
/// a component, a self-contained subgraph of a constraint system.
/// The most important part is that it contains variables and constraints between them.
pub trait ComponentSpec: Index<&'static str> + IndexMut<&'static str> {
    /// The variable type. It has more information than just the [`Value`](Self::Value).
    type Value;
    /// The type of the constraints of the component.
    type Constraint: ConstraintSpec;
    /// Constructs a new [`ComponentSpec`] with the specified name, values and constraints.
    fn new(
        name: String,
        values: Vec<impl Into<Self::Value>>,
        constraints: Vec<Self::Constraint>,
    ) -> Self;
    /// Returns the number of variables in the component.
    fn n_variables(&self) -> usize;
    /// Returns the number of constraints in the component.
    fn n_constraints(&self) -> usize {
        self.constraints().len()
    }
    /// Returns a slice of the constraints in the component.
    fn constraints(&self) -> &[Self::Constraint];
    /// Returns a mutable slice of the constraints in the component.
    fn constraints_mut(&mut self) -> &mut Vec<Self::Constraint>;
    /// Adds a new constraint to the component.
    fn add_constraint(&mut self, constraint: Self::Constraint);
    /// Removes the last constraint from the component.
    fn pop_constraint(&mut self) -> Option<Self::Constraint>;
    /// Removes a specific constraint from a component.
    fn remove_constraint(&mut self, idx: usize) -> Self::Constraint;
    /// Returns the ranking of variables.
    fn ranking(&self) -> Vec<usize>;
}