12 unstable releases (3 breaking)

0.4.2 Mar 27, 2023
0.4.1 Mar 27, 2023
0.3.2 Mar 27, 2023
0.2.0 Jun 8, 2021
0.1.4 May 30, 2021

#306 in Configuration

MIT/Apache

40KB
699 lines

simple_predicates -- a library for modelling simple boolean predicates

A predicate is a formula that can be evaluated to true or false as a function of the values of the variables that occur in it. In simple_predicates, the variables denoted by a user-chosen type satisfying the Eval trait (which requires Clone and PartialEq.) The Eval trait also provides an associated Context type which can be used to provide contextual data needed to resolve the variables. The Expr, Cnf, and Dnf types can be used to construct evaluable expressions.

Installation

Add the following to your Cargo.toml:

[dependencies]
simple_predicates = "0.2"

Features

Feature Description
"serde" Enables serialization and deserialization of data using serde.

By default, there are no features enabled.

Example Usage

Lets say we want to write boolean expressions denoting the possibility of a Vec relating to some u32 values according to the Vec::contains method. We start by implementing Eval:

use simple_predicates::Eval;

// Wrapper struct needed because `u32` & `Eval` are both foreign.
#[derive(Clone, PartialEq)]
struct Contains(pub u32);


impl Eval for Contains {
    type Context = Vec<u32>;

    fn eval(&self, data: &Self::Context) -> bool {
        // Evaluate the u32 by checking if it is in the `Vec`.
        data.contains(&self.0)
    }
}

Now we can check arbitrary containment conditions on a given Vec like so:

use simple_predicates::Eval;
use simple_predicates::Expr::*;

let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];

// `eval` is `true` if input contains 4 but not 5.
let expr = And(
    Box::new(Var(Contains(4))),
    Box::new(Not(Box::new(Var(Contains(5))))));

assert!(expr.eval(&items));

Cnf / Dnf

For more complex expressions, the nesting of And and Or expressions can get very tedious, so the Cnf and Dnf types are provided to simplify their handling.

The Cnf type represents the Conjunctive Normal Form of a boolean expression; a set of expressions which are Anded together. The Dnf type represents the Disjunctive Normal Form of a boolean expression; a set of expressions which are Ored together.

The Cnf and Dnf types can only be used if the variable type implements Eq and Hash. They have identical APIs, so the examples below are representative of either.

Examples

A Cnf can be constructed from an Expr, using the From trait:

use simple_predicates::Eval;
use simple_predicates::Expr::*;

let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];

let cnf = Cnf::from(
    And(
        Box::new(Var(Contains(4))),
        Box::new(Not(Box::new(Var(Contains(5)))))));

assert!(cnf.eval(&items));

A Cnf can also be constructed from anything that emits Exprs with the IntoIterator trait:

use simple_predicates::Eval;
use simple_predicates::Expr::*;

let items: Vec<u32> = vec![1, 2, 4, 7, 9, 10];

let cnf = Cnf::from(vec![
    Var(Contains(4)),
    Not(Box::new(Var(Contains(5)))),
]);

assert!(cnf.eval(&items));

License

simple_predicates is licenced with the MIT license or the Apache version 2.0 license, at your option.

Dependencies

~165KB