Propositional Logic#

Summary#

Propositional Logic (plog) system is an abstract data type defining logical relationships between variables in a combinatorial optimization manner.

Data types#

puan.logic.plog.AtLeast : AtLeast is a compound proposition which takes propositions and represents a lower bound on the result of those propositions. For example, select at least one of x, y and z would be defined as AtLeast(propositions=["x","y","z"], value=1) and represented by the linear inequality \(x+y+z \ge 1\).

puan.logic.plog.AtMost : AtMost is a compound proposition which takes propositions and represents a lower bound on the result of those propositions. For example, select at most two of x, y and z would be defined as AtMost(propositions=["x","y","z"], value=2) and represented by the linear inequality \(-x-y-z \ge -2\).

puan.logic.plog.All : All is a compound proposition representing a conjunction of all given propositions. All is represented by an AtLeast proposition with value set to the number of given propositions. For example, All("x","y","z") is equivalent to AtLeast(propositions=["x","y","z"], value=3).

puan.logic.plog.Any : Any is a compound proposition representing a disjunction of all given propositions. Any is represented by an AtLeast proposition with value set to 1. For example, Any("x","y","z") is equivalent to AtLeast(propositions=["x","y","z"], value=1).

puan.logic.plog.Imply : Imply is the implication logic operand and has two main inputs: condition and consequence. For example, if x is selected then y and z must be selected could be defined with the Imply class as Imply("x", All("y","z")).

puan.logic.plog.Xor : Xor is restricting all propositions within to be selected exactly once. For example, Xor("x","y","z") means that one and exactly one of x, y and z must be selected.

puan.logic.plog.XNor : XNor is a negated Xor. In the special case of two propositions, this is equivalent to the biconditional logical connective (<->).

puan.logic.plog.Not : Not is negating a proposition. For example, Not(All("x","y","z")) means that x, y and z can never be selected all together and is equivalent to AtMost(propositions=["x","y","z"], value=2).

AtLeast#

class AtLeast(value: int, propositions: List[Union[str, Proposition]], variable: Optional[Union[str, variable]] = None, sign: Optional[Sign] = None)#

Bases: Proposition

AtLeast proposition is in its core a regular at least expression (e.g. \(x+y+z \ge 1\)), but restricted to having only +1 or -1 as variable coefficients. This is set by the sign parameter. An AtLeast proposition is considered invalid if there are no sub propositions given.

Parameters
valueinteger value constraint constant - right hand side of the inequality
propositionsa list of puan.Proposition instances or str
variablevariable connected to this proposition
signmarking wheather coefficients before each sub proposition are 1 (Sign.POSITIVE) or -1 (Sign.NEGATIVE).
Raises
Exception
If sign is not -1 or 1.
If propositions is either empty or None.
If variable.bounds is not (0, 1).

Notes

  • propositions may take on any integer value given by their inner bounds, i.e. they are not restricted to boolean values.

  • propositions list cannot be empty.

  • variable may be of type puan.variable, str or None.

    • If str, a default puan.variable will be constructed with its id=variable.

    • If None, then an id will be generated based on its propositions, value and sign.

Examples

At least one of x, y and z.
>>> AtLeast(1, list("xyz"), variable="A")
A: +(x,y,z)>=1
At least three of a, b and c.
>>> AtLeast(value=3, propositions=list("abc"), variable="A")
A: +(a,b,c)>=3
At least eight of t. Notice the dtype on variable t
>>> AtLeast(value=8, propositions=[puan.variable("t", dtype="int")], variable="A")
A: +(t)>=8

Methods

assume(new_variable_bounds)

Assumes something about variable's bounds and returns a new proposition with these new bounds set.

atomic_propositions

All propositions of type puan.variable.

bounds

Variable bounds of this proposition.

compound_propositions

All propositions of (inheriting) type AtLeast.

equation_bounds

The range of values the left hand side of equations on the form \(ax + by + cz - value(bias) \ge 0\) can take.

errors()

Checks this proposition and returns a list of PropositionValidationError's.

evaluate(interpretation)

Evaluates interpretation on this model.

evaluate_propositions(interpretation[, out])

Evaluates propositions on this model given a dict with variables and their bounds/constants.

flatten()

Returns all its propositions and their sub propositions as a unique list of propositions.

from_json(data, class_map)

Convert from JSON data to a proposition.

from_short(short)

From short data format into an AtLeast proposition.

id

Id of this proposition.

is_contradiction

Returns wheather or not this proposition is false, no matter the interpretation of its propositions.

is_tautology

Returns wheather or not this proposition is true, no matter the interpretation of its propositions.

negate()

Negates proposition.

reduce()

Reduces proposition by removing all variables with fixed bound.

solve(objectives[, solver, ...])

Maximises objective in objectives such that this model's constraints are fulfilled and returns a solution for each objective.

to_b64([str_decoding])

Packs data into a base64 string.

to_ge_polyhedron([active, reduced])

Converts into a ge_polyhedron.

to_json()

Returns proposition as a readable JSON.

to_short()

short is a tuple format with five element types: (0) id, (1) sign, (2) propositions, (3) bias (4) bounds.

to_text()

Returns a readable, concise, version controllable text format.

variables

All variables in this proposition (including sub propositions).

assume(new_variable_bounds: Dict[str, Union[int, Tuple[int, int], Bounds]]) Proposition#

Assumes something about variable’s bounds and returns a new proposition with these new bounds set. Other variables, not declared in new_variable_bounds, may also get new bounds as a consequence from the ones set in new_variable_bounds.

Parameters
new_variable_boundstyping.Dict[str, Union[int, Tuple[int, int], puan.Bounds]]

A dict of ids and either int, tuple or puan.Bounds as bounds for the variable.

Returns
outpuan.Proposition

See also

reduce

Notes

All propositions are still kept within this proposition after assume. What may have happen is that proposition’s bounds have tightened.

Examples

Notice in this example that x bounds are changed from (0,1) to (1,1). Also that the model is a tautology after the assumptions.

>>> model = Any(*"xy", variable="A")
>>> model.propositions
[variable(id='x', bounds=Bounds(lower=0, upper=1)), variable(id='y', bounds=Bounds(lower=0, upper=1))]
>>> model.is_tautology
False
>>> model_assumed = model.assume({"x": 1}) # fixes x bounds to (1,1)
>>> model_assumed.propositions
[variable(id='x', bounds=Bounds(lower=1, upper=1)), variable(id='y', bounds=Bounds(lower=0, upper=1))]
>>> model_assumed.is_tautology
True
property atomic_propositions: Iterable[puan.variable]#

All propositions of type puan.variable.

Returns
outIterable[puan.variable]

Examples

>>> proposition = AtLeast(value=1,
...     propositions=["a", AtLeast(value=2, propositions=list("xy"), variable="B")],
...     variable="A")
>>> list(proposition.atomic_propositions)
[variable(id='a', bounds=Bounds(lower=0, upper=1))]
property bounds: puan.Bounds#

Variable bounds of this proposition.

Returns
outpuan.Bounds
property compound_propositions: Iterable[puan.Proposition]#

All propositions of (inheriting) type AtLeast.

Returns
outIterable[puan.Proposition]

Examples

>>> proposition = AtLeast(value=1,
...     propositions=["a", AtLeast(value=2, propositions=list("xy"), variable="B")],
...     variable="A")
>>> list(proposition.compound_propositions)
[B: +(x,y)>=2]
property equation_bounds: Tuple[int, int]#

The range of values the left hand side of equations on the form \(ax + by + cz - value(bias) \ge 0\) can take.

Returns
outTuple[int, int]

Examples

>>> model = AtLeast(1,["x","y"])
>>> model.equation_bounds
(-1, 1)
>>> model = AtLeast(2,["x","y"])
>>> model.equation_bounds
(-2, 0)
>>> model = AtMost(1,["x","y"])
>>> model.equation_bounds
(-1, 1)
>>> model = AtMost(2,["x","y"])
>>> model.equation_bounds
(0, 2)
errors() List[PropositionValidationError]#

Checks this proposition and returns a list of PropositionValidationError’s. An error in the result is due to one or more of the following:

  • It exist at least one circular variable dependency.

  • A variable depends directly on two or more variables with identical ids.

  • There exists two or more variables with identical ids but with different bounds.

Returns
outList[PropositionValidationError]

Examples

>>> All(*"xyz", variable="A").errors()
[]
>>> All(*"A", variable="A").errors()
[<PropositionValidationError.CIRCULAR_DEPENDENCIES: 'CIRCULAR_DEPENDENCIES'>]
>>> All(Any(*"ab", variable="A"), Any(puan.variable("A", (-10,10)))).errors()
[<PropositionValidationError.AMBIVALENT_VARIABLE_DEFINITIONS: 'AMBIVALENT_VARIABLE_DEFINITIONS'>]
evaluate(interpretation: Dict[str, Union[int, Tuple[int, int], Bounds]]) Bounds#

Evaluates interpretation on this model. It will evaluate sub propositions bottoms-up and propagate results upwards. This means that even though intermediate variables are not set in interpretation, they (may) receive a new bound based on the evaluation of its propositions.

Parameters
interpretationDict[str, Union[puan.Bounds, Tuple[int,int], int]]

the values of the variables in the model to evaluate it for

Returns
outbool

See also

evaluate_propositions

Evaluates propositions on this model given a dict with variables and their bounds/constants.

Examples

>>> All(*"xy", variable="A").evaluate({"x": 1})
Bounds(lower=0, upper=1)
>>> All(*"xy", variable="A").evaluate({"x": (1,1)})
Bounds(lower=0, upper=1)
>>> All(*"xy", variable="A").evaluate({"x": puan.Bounds(1,1)})
Bounds(lower=0, upper=1)
>>> All(*"xy", variable="A").evaluate({"x": 1, "y": 1})
Bounds(lower=1, upper=1)
>>> AtLeast(propositions=[puan.variable("x", dtype="int")],
... value=10).evaluate({"x": 9})
Bounds(lower=0, upper=0)
>>> AtLeast(propositions=[puan.variable("x", dtype="int")],
... value=10).evaluate({"x": 10})
Bounds(lower=1, upper=1)
evaluate_propositions(interpretation: ~typing.Dict[str, ~typing.Union[int, ~typing.Tuple[int, int], ~puan.Bounds]], out: ~typing.Callable[[~puan.Bounds], ~typing.Union[~puan.Bounds, ~typing.Tuple[int, int], int]] = <function AtLeast.<lambda>>) Dict[str, Bounds]#

Evaluates propositions on this model given a dict with variables and their bounds/constants.

Parameters
interpretationDict[Union[str, puan.variable], int]

the values of the variables in the model to evaluate it for

outCallback[[puan.Bounds], Union[puan.Bounds, Tuple[int,int], int]]

an optional callback function for changing output data type.

Returns
outDict[str, Union[puan.Bounds, Tuple[int,int], int]]

See also

evaluate

Evaluates interpretation on this model.

Notes

A variable’s new bound, which is not included in the initial dict, is calculated from its sub proposition’s bounds or kept unchanged.

Examples

>>> All(*"xy", variable="A").evaluate_propositions({"x": 1})
{'A': Bounds(lower=0, upper=1), 'x': Bounds(lower=1, upper=1), 'y': Bounds(lower=0, upper=1)}
>>> All(*"xy", variable="A").evaluate_propositions({"x": 1, "y": 1})
{'A': Bounds(lower=1, upper=1), 'x': Bounds(lower=1, upper=1), 'y': Bounds(lower=1, upper=1)}
>>> All(*"xy", variable="A").evaluate_propositions({"x": 1, "y": (1,1)})
{'A': Bounds(lower=1, upper=1), 'x': Bounds(lower=1, upper=1), 'y': Bounds(lower=1, upper=1)}
>>> All(*"xy", variable="A").evaluate_propositions({"x": puan.Bounds(1,1), "y": (1,1)})
{'A': Bounds(lower=1, upper=1), 'x': Bounds(lower=1, upper=1), 'y': Bounds(lower=1, upper=1)}
>>> All(*"xy", variable="A").evaluate_propositions({"x": puan.Bounds(1,1), "y": (1,1)}, out=lambda x: x.constant)
{'A': 1, 'x': 1, 'y': 1}
>>> AtLeast(propositions=[puan.variable("x", (0, 10))],
... value=10).evaluate_propositions({"x": 9})
{'VAR2fa10da7075e3abf61065cb37ecd6bb658b38c9fdd0a1b1a69e34d541d32bd2d': Bounds(lower=0, upper=0), 'x': Bounds(lower=9, upper=9)}
>>> AtLeast(propositions=[puan.variable("x", dtype="int")],
... value=10).evaluate_propositions({"x": 10})
{'VAR2fa10da7075e3abf61065cb37ecd6bb658b38c9fdd0a1b1a69e34d541d32bd2d': Bounds(lower=1, upper=1), 'x': Bounds(lower=10, upper=10)}
flatten() List[Proposition]#

Returns all its propositions and their sub propositions as a unique list of propositions.

Returns
outList[puan.Proposition]

Examples

>>> proposition = AtLeast(1, [AtLeast(1, ["a", "b"], "B"),
... AtLeast(1, ["c", "d"], "C"), "e"], "A")
>>> proposition.flatten()
[A: +(B,C,e)>=1, B: +(a,b)>=1, C: +(c,d)>=1, variable(id='a', bounds=Bounds(lower=0, upper=1)), variable(id='b', bounds=Bounds(lower=0, upper=1)), variable(id='c', bounds=Bounds(lower=0, upper=1)), variable(id='d', bounds=Bounds(lower=0, upper=1)), variable(id='e', bounds=Bounds(lower=0, upper=1))]
static from_json(data: Dict[str, Any], class_map: list) AtLeast#

Convert from JSON data to a proposition.

Parameters
class_maplist

A list of classes implementing the puan.Proposition protocol. They’ll be mapped from type attribute in the json data.

Returns
outAtLeast

Notes

Propositions within data not having type attribute will be considered a puan.variable.

Examples

>>> AtLeast.from_json({"type": "AtLeast", "propositions": [{"id":"x"},{"id":"y"},{"id":"z"}], "id": "A"}, [puan.variable, AtLeast])
A: +(x,y,z)>=1
static from_short(short: Tuple[str, Sign, List[str], int, List[int]]) AtLeast#

From short data format into an AtLeast proposition. A short data format is a tuple of id, sign, variables, bias and bounds.

Returns
outAtLeast
Raises
Exception

If tuple is not of size 5.

Examples

>>> AtLeast.from_short(("A", 1, ["a","b","c"], -1, [0,1]))
A: +(a,b,c)>=1
>>> AtLeast.from_short(("x", 1, [], 0, [-10,10]))
variable(id='x', bounds=Bounds(lower=-10, upper=10))
property id: str#

Id of this proposition.

Returns
outstr
property is_contradiction: bool#

Returns wheather or not this proposition is false, no matter the interpretation of its propositions.

Returns
outbool

Notes

Sub propositions are not taken into consideration.

Examples

>>> model = AtLeast(1,["x","y"])
>>> model.is_contradiction
False
>>> model = AtMost(1,["x","y"])
>>> model.is_contradiction
False
>>> model = AtLeast(3,["x","y"])
>>> model.is_contradiction
True
>>> model = AtMost(-1,["x","y"])
>>> model.is_contradiction
True
property is_tautology: bool#

Returns wheather or not this proposition is true, no matter the interpretation of its propositions.

Returns
outbool

Notes

Sub propositions are not taken into consideration.

Examples

>>> model = AtLeast(1,["x","y"])
>>> model.is_tautology
False
>>> model = AtMost(1,["x","y"])
>>> model.is_tautology
False
>>> model = AtMost(3,["x","y","z"])
>>> model.is_tautology
True
>>> model = AtLeast(0, ["x"], sign=1)
>>> model.is_tautology
True
>>> model = AtMost(2,["x","y"])
>>> model.is_tautology
True
negate() Proposition#

Negates proposition.

Returns
outpuan.Proposition

Examples

>>> AtLeast(2, ["x","y","z"], variable="A").negate()
A: -(x,y,z)>=-1
>>> AtLeast(3, ["x","y","z"], variable="A").negate()
A: -(x,y,z)>=-2
>>> AtLeast(-1, ["x","y","z"], variable="A", sign=puan.Sign.NEGATIVE).negate()
A: +(x,y,z)>=2
reduce() Proposition#

Reduces proposition by removing all variables with fixed bound. Returns a potentially reduced proposition.

Returns
outpuan.Proposition

See also

assume

Examples

>>> All(puan.variable("x", (1,1)), *"yz", variable="A").reduce()
A: +(y,z)>=2
>>> # Note that x is no longer part of the proposition and
>>> # the value of the proposition is updated from 3 to 2
>>> # as a result of x being 1
>>> All(puan.variable("x", (1,1)), puan.variable("y", (0,0)), variable="A").reduce()
variable(id='A', bounds=Bounds(lower=0, upper=0))
>>> # If the remaining proposition is a puan.variable and only a puan.varialbe it is kept with updated bounds
>>> # Any other constant proposition will be reduced
solve(objectives: List[Dict[Union[str, variable], int]], solver: Optional[Callable[[ge_polyhedron, Iterable[numpy.ndarray]], Iterable[Tuple[Optional[numpy.ndarray], Optional[int], int]]]] = None, try_reduce_before: bool = False, include_virtual_variables: bool = False) starmap#

Maximises objective in objectives such that this model’s constraints are fulfilled and returns a solution for each objective.

Parameters
objectivesList[Dict[Union[str, puan.variable], int]]

A list of objectives as dictionaries. Keys are either variable ids as strings or a puan.variable. Values are objective value for the key.

solverCallable[[puan.ndarray.ge_polyhedron, Dict[str, int]], List[(np.ndarray, int, int)]] = None

If None is provided puan’s own (beta) solver is used. If you want to provide another solver you have to send a function as solver parameter. That function has to take a puan.ndarray.ge_polyhedron and a 2d numpy array representing all objectives, as input. NOTE that the polyhedron DOES NOT provide constraints for variable bounds. Variable bounds are found under each variable under polyhedron.variables and constraints for these has to manually be created and added to the polyhedron matrix. The function should return a list, one for each objective, of tuples of (solution vector, objective value, status code). The solution vector is an integer ndarray vector of size equal to width of polyhedron.A. There are six different status codes from 1-6:

  • 1: solution is undefined

  • 2: solution is feasible

  • 3: solution is infeasible

  • 4: no feasible solution exists

  • 5: solution is optimal

  • 6: solution is unbounded

Checkout https://github.com/ourstudio-se/puan-solvers for quick how-to’s for common solvers.

try_reduce_beforebool = False

If true, then methods will be applied to try and reduce size of this model before running solve function.

include_virtual_variablesbool = False

If true, the virtual/artificial variables that has automatically been generated creating the model will be included in solutions

Returns
outitertools.starmap:

Notes

Currently a beta solver is used, DO NOT USE THIS IN PRODUCTION. If no solution could be found, None is returned.

Examples

>>> dummy_solver = lambda x,y: list(map(lambda v: (v, 0, 5), y))
>>> list(All(*"ab").solve([{"a": 1, "b": 1}], dummy_solver))
[({'a': 1, 'b': 1}, 0, 5)]
to_b64(str_decoding: str = 'utf8') str#

Packs data into a base64 string.

Parameters
str_decoding: str = ‘utf8’
Returns
outstr
to_ge_polyhedron(active: bool = False, reduced: bool = False) ge_polyhedron#

Converts into a ge_polyhedron.

Parameters
activebool = False

If true, then the top node id will be assumed to be true.

reducedbool = False

If true, then methods will be applied to the polyhedron in an attempt to reduce its size.

Returns
outpuan.ndarray.ge_polyhedron
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

Examples

>>> All("x","y","z",variable="A").to_json()
{'type': 'All', 'propositions': [{'id': 'x'}, {'id': 'y'}, {'id': 'z'}], 'id': 'A'}
to_short() Tuple[str, int, List[str], int, List[int]]#

short is a tuple format with five element types: (0) id, (1) sign, (2) propositions, (3) bias (4) bounds.

Returns
outTuple[str, int, List[str], int, List[int]]

Notes

to_short() does not include sub propositions if any

Examples

>>> All("x","y","z",variable="A").to_short()
('A', 1, ['x', 'y', 'z'], -3, [0, 1])
to_text() str#

Returns a readable, concise, version controllable text format.

Returns
outstr
property variables: List[puan.variable]#

All variables in this proposition (including sub propositions).

Returns
outList[puan.variable]

AtMost#

class AtMost(value: int, propositions: List[Union[str, variable]], variable: Optional[Union[str, variable]] = None)#

Bases: AtLeast

AtMost proposition is an at least expression with negative coefficients and positive bias (e.g. \(-x-y-z+1 \ge 0\)). Sub propositions may take on any value given by their equation bounds

Parameters
valueinteger value constraint constant - right hand side of the inequality
propositionsa list of puan.Proposition instances or str
variablevariable connected to this proposition

Notes

Examples

Meaning at most one of x, y and z.
>>> AtMost(1, list("xyz"), variable="A")
A: -(x,y,z)>=-1

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

to_json()

Returns proposition as a readable JSON.

static from_json(data: dict, class_map) AtMost#

Convert from JSON data to a proposition.

Returns
outAtMost
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

All#

class All(*propositions, variable: Optional[Union[str, variable]] = None)#

Bases: AtLeast

All proposition means that all of its propositions must be true, otherwise the proposition is false.

Parameters
*propositionsan iterable of puan.Proposition instances or str
variablevariable connected to this proposition

Notes

Examples

Meaning at least one of x, y and z.
>>> All(*"xyz", variable="A")
A: +(x,y,z)>=3

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

from_list(propositions[, variable])

Convert from list of propositions to an object of this proposition class.

to_json()

Returns proposition as a readable JSON.

static from_json(data: Dict[str, Any], class_map) All#

Convert from JSON data to a proposition.

Returns
outAll
static from_list(propositions: list, variable: Optional[Union[str, variable]] = None) All#

Convert from list of propositions to an object of this proposition class.

Returns
outAll

Examples

>>> model = All.from_list([puan.variable("x"), puan.variable("y")], variable="a")
>>> type(model) == All
True
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

Any#

class Any(*propositions, variable: Optional[Union[str, variable]] = None)#

Bases: AtLeast

Any proposition means that at least one of its propositions must be true, otherwise the proposition is false.

Parameters
*propositionsan iterable of puan.Proposition instances or str
variablevariable connected to this proposition

Notes

Examples

Meaning at least one of x, y and z.
>>> Any(*"xyz", variable="A")
A: +(x,y,z)>=1

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

from_list(propositions[, variable])

Convert from list of propositions to an object of this proposition class.

to_json()

Returns proposition as a readable JSON.

static from_json(data: Dict[str, Any], class_map) Any#

Convert from JSON data to a proposition.

Returns
outAny
static from_list(propositions: List[Union[AtLeast, variable]], variable: Optional[Union[str, variable]] = None) Any#

Convert from list of propositions to an object of this proposition class.

Returns
outAny

Examples

>>> model = Any.from_list([puan.variable("x"), puan.variable("y")], variable="a")
>>> type(model) == Any
True
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

Imply#

class Imply(condition, consequence, variable: Optional[Union[str, variable]] = None)#

Bases: Any

Imply proposition consists of two sub propositions: condition and consequence. An implication proposition says that if the condition is true then the consequence must be true. Otherwise the proposition is false.

Parameters
conditionan instance of puan.Proposition data type or str
consequencean instance of puan.Proposition data type or str
variablevariable connected to this proposition

Notes

Examples

Meaning at least one of x, y and z.
>>> Imply(condition=All(*"abc", variable="B"), consequence=Any(*"xyz", variable="C"), variable="A")
A: +(B,C)>=1

Methods

from_cicJE(data[, id_ident, cmp2prop])

This function converts a cicJE into an Imply.

from_json(data, class_map)

Convert from JSON data to a proposition.

to_json()

Returns proposition as a readable JSON.

static from_cicJE(data: Dict[str, Any], id_ident: str = 'id', cmp2prop: Optional[Callable[[dict], variable]] = None) Imply#

This function converts a cicJE into an Imply.

Parameters
dataDict[str, Any]
id_identstr = “id”

The id identifier inside a component

Returns
outImply

Examples

>>> Imply.from_cicJE({
...     "id": "someId",
...     "condition": {
...         "relation": "ALL",
...         "subConditions": [
...             {
...                 "relation": "ALL",
...                 "components": [
...                     {"id": "a"},
...                     {"id": "b"},
...                 ]
...             }
...         ]
...     },
...     "consequence": {
...         "ruleType": "REQUIRES_ALL",
...         "components": [
...             {"id": "x"},
...             {"id": "y"},
...             {"id": "z"},
...         ]
...     }
... })
someId: +(VAR180540a846781f231b3c1fb0422d95e48e9b9379a5ec6890a0b9a32cb7f66b75,VAR9b4a27f7babf7022c3cadd7e00de9f6da1747f82c5c95960f76138599c35b52c)>=1
static from_json(data: Dict[str, Any], class_map) Imply#

Convert from JSON data to a proposition.

Returns
outImply
Raises
Exception

If no consequence key in data.

to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

Xor#

class Xor(*propositions, variable: Optional[Union[str, variable]] = None)#

Bases: All

Xor proposition is true when exactly one of its propositions is true, e.g. \(x+y+z = 1\)

Parameters
*propositionsan iterable of puan.Proposition instances or str
variablevariable connected to this proposition

Notes

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

from_list(propositions[, variable])

Convert from list of propositions to an object of this proposition class.

to_json()

Returns proposition as a readable JSON.

classmethod from_json(data: dict, class_map) Xor#

Convert from JSON data to a proposition.

Returns
outXor
classmethod from_list(propositions: List[Union[AtLeast, variable]], variable: Optional[Union[str, variable]] = None) Xor#

Convert from list of propositions to an object of this proposition class.

Returns
outXor

Examples

>>> model = Xor.from_list([puan.variable("x"), puan.variable("y")], variable="a")
>>> type(model) == Xor
True
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

XNor#

class XNor(*propositions, variable: Optional[Union[str, variable]] = None)#

Bases: Any

XNor proposition is a negated Xor, i.e. “exactly one” configurations will be false or \(x+y+z\neq1\).

Parameters
*propositionsan iterable of puan.Proposition instances or str
variablevariable connected to this proposition

Notes

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

from_list(propositions[, variable])

Convert from list of propositions to an object of this proposition class.

to_json()

Returns proposition as a readable JSON.

static from_json(data: dict, class_map) XNor#

Convert from JSON data to a proposition.

Returns
outAtLeast
static from_list(propositions: list, variable: Optional[Union[str, variable]] = None) AtLeast#

Convert from list of propositions to an object of this proposition class.

Returns
outAtLeast

Notes

XNor is not its own type but instead returns an AtLeast proposition which preserves the same logic.

Examples

>>> model = XNor.from_list([puan.variable("x"), puan.variable("y")], variable="a")
>>> type(model) == XNor
True
to_json() Dict[str, Any]#

Returns proposition as a readable JSON.

Returns
outDict[str, Any]

Not#

class Not(proposition)#

Bases: object

Not proposition negates the input proposition.

Parameters
propositionan instance of puan.Proposition or str

Notes

Methods

from_json(data, class_map)

Convert from JSON data to a proposition.

static from_json(data: Dict[str, Any], class_map) AtLeast#

Convert from JSON data to a proposition.

Returns
outAtLeast
Raises
Exception

If no proposition key in data.

PropositionValidationError#

class PropositionValidationError(value)#

Bases: str, Enum

An enumeration.

AMBIVALENT_VARIABLE_DEFINITIONS = 'AMBIVALENT_VARIABLE_DEFINITIONS'#
CIRCULAR_DEPENDENCIES = 'CIRCULAR_DEPENDENCIES'#
NON_UNIQUE_SUB_PROPOSITION_SET = 'NON_UNIQUE_SUB_PROPOSITION_SET'#