Crux.Formula (crux v0.1.2)

View Source

A module for representing and manipulating satisfiability formulas in Conjunctive Normal Form (CNF).

Summary

Types

An affirmed_literal() is a positive integer representing a variable that is asserted to be true.

See bindings/1.

A binding() maps a positive integer (the variable) to its original value.

A clause is a disjunction of literal()s.

A formula in Conjunctive Normal Form (CNF) is a conjunction of clauses, where each clause() is a disjunction of literal()s.

A literal() is either an affirmed_literal() (a positive integer) or a negated_literal() (a negative integer).

A negated_literal() is a negative integer representing a variable that is asserted to be false.

A reverse binding maps a variable to its positive integer representation. This provides O(log n) lookup for variable-to-integer mappings.

t()

See t/1.

A satisfiability formula in Conjunctive Normal Form (CNF) along with bindings that map the integers used in the CNF back to their original values.

Functions

Converts a boolean expression to a SAT formula in Conjunctive Normal Form (CNF).

Converts a SAT formula back to a boolean expression.

Formats a CNF formula to PicoSAT DIMACS format.

Types

affirmed_literal()

@type affirmed_literal() :: pos_integer()

An affirmed_literal() is a positive integer representing a variable that is asserted to be true.

bindings()

@type bindings() :: bindings(term())

See bindings/1.

bindings(variable)

@type bindings(variable) :: %{required(pos_integer()) => variable}

A binding() maps a positive integer (the variable) to its original value.

clause()

@type clause() :: [literal(), ...]

A clause is a disjunction of literal()s.

A clause is satisfied if at least one of its literal()s is satisfied.

cnf()

@type cnf() :: [clause()]

A formula in Conjunctive Normal Form (CNF) is a conjunction of clauses, where each clause() is a disjunction of literal()s.

All clause()s of a CNF formula must be satisfied for the formula to be satisfied.

literal()

@type literal() :: affirmed_literal() | negated_literal()

A literal() is either an affirmed_literal() (a positive integer) or a negated_literal() (a negative integer).

negated_literal()

@type negated_literal() :: neg_integer()

A negated_literal() is a negative integer representing a variable that is asserted to be false.

reverse_bindings(variable)

@type reverse_bindings(variable) :: %{required(variable) => pos_integer()}

A reverse binding maps a variable to its positive integer representation. This provides O(log n) lookup for variable-to-integer mappings.

t()

@type t() :: t(term())

See t/1.

t(variable)

@type t(variable) :: %Crux.Formula{
  bindings: bindings(variable),
  cnf: cnf(),
  reverse_bindings: reverse_bindings(variable)
}

A satisfiability formula in Conjunctive Normal Form (CNF) along with bindings that map the integers used in the CNF back to their original values.

Functions

from_expression(expression)

@spec from_expression(Crux.Expression.t(variable)) :: t(variable)
when variable: term()

Converts a boolean expression to a SAT formula in Conjunctive Normal Form (CNF).

Examples

iex> import Crux.Expression
...> expression = b(:a and :b)
...> Formula.from_expression(expression)
%Formula{
  cnf: [[1], [2]],
  bindings: %{1 => :a, 2 => :b},
  reverse_bindings: %{a: 1, b: 2}
}

iex> expression = b(:x or not :y)
...> Formula.from_expression(expression)
%Formula{
  cnf: [[1, -2]],
  bindings: %{1 => :x, 2 => :y},
  reverse_bindings: %{x: 1, y: 2}
}

to_expression(formula)

@spec to_expression(formula :: t(variable)) :: Crux.Expression.cnf(variable)
when variable: term()

Converts a SAT formula back to a boolean expression.

Examples

iex> formula = %Formula{
...>   cnf: [[1], [2]],
...>   bindings: %{1 => :a, 2 => :b},
...>   reverse_bindings: %{a: 1, b: 2}
...> }
...>
...> Formula.to_expression(formula)
b(:a and :b)

iex> formula = %Formula{
...>   cnf: [[1, -2]],
...>   bindings: %{1 => :x, 2 => :y},
...>   reverse_bindings: %{x: 1, y: 2}
...> }
...>
...> Formula.to_expression(formula)
b(:x or not :y)

to_picosat(formula)

@spec to_picosat(t()) :: String.t()

Formats a CNF formula to PicoSAT DIMACS format.

Takes a formula struct and returns a string in the DIMACS CNF format that can be consumed by SAT solvers like PicoSAT.

Examples

iex> alias Crux.{Expression, Formula}
...> formula = Formula.from_expression(Expression.b(:a and :b))
...> Formula.to_picosat(formula)
"p cnf 2 2\n1 0\n2 0"