Propositional requirements¶
The backend for propositional requirements — boolean logic, written as Horn
rules (head :- body) or disjunctive clauses (y_0 or not y_1). This backend
also provides the Memory-efficient Loss (a memory-efficient t-norm loss
inspired by Logic Tensor Networks, LTN).
Shield Layer¶
shield_layer ¶
The propositional Shield Layer.
Defines :class:ShieldLayer, a differentiable PyTorch layer that corrects a model's
predictions so they provably satisfy a set of propositional requirements. The
requirements are normalised into clauses, stratified into ordered layers, and applied
in order by per-stratum :class:ConstraintsModule modules.
ShieldLayer ¶
ShieldLayer(num_classes: int, requirements: Union[str, List[ConstraintsGroup]] = None, ordering_choice: str = None, custom_ordering: str = None)
Bases: Module
Differentiable layer that corrects predictions so they satisfy a set of propositional
requirements over binary variables (the num_classes outputs, interpreted as probabilities).
The requirements are normalised into clauses and then stratified: each clause is assigned to a
layer (stratum) such that a clause's head is only corrected after the variables in its body, with
the centrality/ordering deciding which variable plays the head when there is a choice. Each
stratum becomes a ConstraintsModule, and forward applies the modules in order, so correcting
one stratum never violates an earlier one — guaranteeing all requirements hold on the output.
requirements may be either a path to a constraints file or a precomputed list of strata.
Build the layer by stratifying the requirements into correction modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
int
|
The number of output variables (labels) the layer operates on. |
required |
requirements
|
Union[str, List[ConstraintsGroup]]
|
Either a path to a constraints file or a precomputed list of
strata (:class: |
None
|
ordering_choice
|
str
|
The variable-ordering / centrality strategy used to decide which variable plays the head during stratification. |
None
|
custom_ordering
|
str
|
An optional explicit comma-separated variable order; with a
|
None
|
Raises:
| Type | Description |
|---|---|
Exception
|
If |
Example
layer = ShieldLayer(num_classes=5, ... requirements='constraints.txt', ... ordering_choice='given') corrected = layer(predictions) # predictions: (batch, 5)
Source code in pishield/propositional_requirements/shield_layer.py
from_clauses_group
classmethod
¶
Build a Shield Layer from a clauses group and centrality ordering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of output variables. |
required | |
clauses_group
|
The :class: |
required | |
centrality
|
The centrality / ordering used to stratify the clauses. |
required |
Returns:
| Type | Description |
|---|---|
|
A configured ShieldLayer. |
Source code in pishield/propositional_requirements/shield_layer.py
gradual_prefix ¶
Select the atoms and number of strata covered by a fraction of variables.
Grows the never-corrected core with whole strata until roughly ratio of all
variables are covered; used to gradually enable the requirements in training.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratio
|
The target fraction of variables to cover, in [0, 1]. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
leading strata included. |
Source code in pishield/propositional_requirements/shield_layer.py
slicer ¶
Build a :class:Slicer covering a fraction of the requirements.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratio
|
The target fraction of variables to cover, in [0, 1]. |
required |
Returns:
| Type | Description |
|---|---|
|
A Slicer over the corresponding atoms and leading modules. |
Source code in pishield/propositional_requirements/shield_layer.py
to_minimal ¶
Restrict a tensor to the layer's atom columns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
A tensor of shape (batch, num_classes). |
required |
Returns:
| Type | Description |
|---|---|
|
The tensor restricted to the layer's atoms. |
Source code in pishield/propositional_requirements/shield_layer.py
from_minimal ¶
Scatter a minimal-atom tensor back into a full tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
The minimal tensor over the layer's atoms. |
required | |
init
|
The full tensor to write into. |
required |
Returns:
| Type | Description |
|---|---|
|
|
Source code in pishield/propositional_requirements/shield_layer.py
forward ¶
Correct predictions so they satisfy all requirements.
Restricts the predictions to the constrained atoms, applies each stratum's correction module in order, and scatters the corrected values back into the full prediction tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The model predictions, shape (batch, num_classes). |
required | |
goal
|
Optional goal (ground-truth) assignment to keep corrections consistent with during training. |
None
|
|
iterative
|
If True use the iterative correction implementation. |
True
|
|
slicer
|
Optional :class: |
None
|
Returns:
| Type | Description |
|---|---|
|
The corrected predictions, same shape as |
Example
corrected = layer(predictions)
every requirement now holds on
corrected¶
Source code in pishield/propositional_requirements/shield_layer.py
run_layer ¶
Run a Shield Layer both ways and assert the results agree.
Runs the layer with the iterative and tensor implementations, checks they are numerically close, and optionally exercises a backward pass; mainly a testing/debugging helper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
layer
|
The :class: |
required | |
preds
|
The prediction tensor. |
required | |
backward
|
If True, add a random differentiable perturbation and backpropagate. |
False
|
Returns:
| Type | Description |
|---|---|
|
The corrected predictions (from the iterative implementation), detached. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the two implementations disagree. |
Source code in pishield/propositional_requirements/shield_layer.py
Memory-efficient Loss¶
shield_loss ¶
The propositional Memory-efficient Loss.
Defines :class:ShieldLoss, a t-norm based penalty term that encourages (but does not
enforce) the satisfaction of propositional requirements. It is a memory-efficient
t-norm loss inspired by Logic Tensor Networks (LTN). Each requirement is read as a
disjunction (clause) and its degree of satisfaction is computed under one of three
t-norms - Goedel, Lukasiewicz or product - using sparse matrix representations of the
requirements.
ShieldLoss ¶
Bases: Module
The Memory-efficient Loss: a t-norm based loss term that encourages the satisfaction of propositional requirements. It is a memory-efficient t-norm loss inspired by Logic Tensor Networks (LTN).
Unlike the Shield Layer, the Memory-efficient Loss does not correct the predictions; it returns a scalar penalty (in [0, 1]) which is minimised when the requirements are satisfied. The penalty is computed using one of three t-norms: 'godel', 'product' or 'lukasiewicz'.
The requirements are read from a file whose lines have the form head :- body, where
head is a single literal and body is a (possibly empty) list of literals. A literal
is the index of a variable (e.g. 3) for a positive literal, or that index prefixed with
n (e.g. n3) for a negative literal.
Load the requirements and precompute the t-norm matrices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_variables
|
int
|
The number of variables (labels) the predictions cover. |
required |
requirements_filepath
|
str
|
Path to the requirements file (one |
required |
tnorm_choice
|
str
|
The t-norm to use: |
'godel'
|
Example
loss_fn = ShieldLoss(num_variables=10, ... requirements_filepath='constraints.txt', ... tnorm_choice='product') penalty = loss_fn(predictions) # predictions: (batch, 10)
Source code in pishield/propositional_requirements/shield_loss.py
create_matrices ¶
Build the positive/negative literal matrices used by the t-norm losses.
Combines the body (I) and head (M) encodings into Cplus and
Cminus matrices marking the positive and negative literal appearances in
each requirement's disjunction (the exact combination depends on the chosen
t-norm), and records the number of requirements.
Source code in pishield/propositional_requirements/shield_loss.py
createIs ¶
Encode the body literals of each requirement into indicator matrices.
Reads the requirements file and, for each rule's body, marks which variables
appear as positive (Iplus) and negative (Iminus) literals.
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
num_variables). |
Source code in pishield/propositional_requirements/shield_loss.py
createMs ¶
Encode the head literal of each requirement into indicator matrices.
Reads the requirements file and marks, per requirement, whether its head is a
positive (Mplus) or negative (Mminus) literal at the head's variable.
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
num_requirements); each column corresponds to a requirement and carries a 1 |
|
|
at the head variable's row for the matching polarity. |
Source code in pishield/propositional_requirements/shield_loss.py
get_sparse_representation ¶
Return the sparse indices and values of a requirement matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
req_matrix
|
A dense requirement matrix. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
their values. |
Source code in pishield/propositional_requirements/shield_loss.py
godel_disjunctions_sparse ¶
Compute the Goedel-t-norm requirement penalty.
Each requirement's satisfaction degree is the maximum over its literals' truth values; the penalty is one minus the mean satisfaction degree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predicted probabilities, shape (batch, num_variables). |
required | |
weighted_literals
|
If True, weight each literal by its matrix value. |
False
|
Returns:
| Type | Description |
|---|---|
|
A scalar penalty in [0, 1], minimised when the requirements are satisfied. |
Source code in pishield/propositional_requirements/shield_loss.py
lukasiewicz_disjunctions_sparse ¶
Compute the Lukasiewicz-t-norm requirement penalty.
Each requirement's satisfaction degree is the sum of its literals' truth values clamped to 1; the penalty is one minus the mean satisfaction degree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predicted probabilities, shape (batch, num_variables). |
required | |
weighted_literals
|
If True, weight each literal by its matrix value. |
False
|
Returns:
| Type | Description |
|---|---|
|
A scalar penalty in [0, 1], minimised when the requirements are satisfied. |
Source code in pishield/propositional_requirements/shield_loss.py
product_disjunctions_sparse ¶
Compute the product-t-norm requirement penalty.
The disjunction is computed as the negation of the product of the negated literals; the penalty is one minus the mean satisfaction degree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predicted probabilities, shape (batch, num_variables). |
required | |
weighted_literals
|
If True, weight each literal by its matrix value. |
False
|
Returns:
| Type | Description |
|---|---|
|
A scalar penalty in [0, 1], minimised when the requirements are satisfied. |
Source code in pishield/propositional_requirements/shield_loss.py
Literal¶
literal ¶
Propositional literals.
A literal is a single variable (atom) together with a sign: either the variable asserted positively or its negation. Literals are the atomic building blocks of clauses and constraints in the propositional requirements subpackage.
Literal ¶
A propositional literal: a variable (atom) and a polarity.
Attributes:
| Name | Type | Description |
|---|---|---|
atom |
The integer index of the variable referenced by the literal. |
|
positive |
True if the literal asserts the variable, False if it negates it. |
Build a literal from either an (atom, polarity) pair or a string.
Two calling conventions are supported
Literal(atom: int, positive: bool)builds the literal directly.Literal(text: str)parses a textual literal. Supported forms are'y_3'/'y_not 3'(label notation) and'3'/'n3'(index notation), where thenprefix denotes a negative literal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Either two positional arguments |
()
|
|
reversed_sign
|
When parsing |
False
|
Source code in pishield/propositional_requirements/literal.py
neg ¶
Return a new literal with the opposite polarity.
Returns:
| Type | Description |
|---|---|
|
A Literal over the same atom with flipped sign. |
Clause¶
clause ¶
Propositional clauses.
A clause is a disjunction of literals (e.g. y_0 or not y_1), represented as an
unordered set of :class:Literal objects. Clauses are the normalised form into which
requirements are converted before stratification, and they support the logical
operations (resolution, subsumption, coherency checks) used to build the Shield Layer.
Clause ¶
A disjunction of literals.
Attributes:
| Name | Type | Description |
|---|---|---|
literals |
A frozenset of the :class: |
Build a clause from literals.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
literals
|
Either a whitespace-separated string of literals (e.g.
|
required |
Source code in pishield/propositional_requirements/clause.py
from_constraint
classmethod
¶
Build the clause equivalent to a Horn constraint head :- body.
The constraint head :- b1, b2 is logically head or not b1 or not b2,
so each body literal is negated and the head kept as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
constraint
|
The :class: |
required |
Returns:
| Type | Description |
|---|---|
|
The equivalent Clause. |
Source code in pishield/propositional_requirements/clause.py
random
classmethod
¶
Build a random clause over num_classes variables.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of available variables (atom indices). |
required |
Returns:
| Type | Description |
|---|---|
|
A randomly generated Clause. |
Source code in pishield/propositional_requirements/clause.py
shift_add_n0 ¶
Shift every atom up by one and add the negative literal n0.
Used to make room for a detection variable at index 0.
Returns:
| Type | Description |
|---|---|
|
A new Clause with shifted atoms plus the |
Source code in pishield/propositional_requirements/clause.py
fix_head ¶
Turn the clause into a constraint by designating one literal as the head.
The remaining literals become the (negated) body, inverting
:meth:from_constraint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
head
|
The literal of this clause to use as the constraint head. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
class: |
Raises:
| Type | Description |
|---|---|
Exception
|
If |
Source code in pishield/propositional_requirements/clause.py
always_true ¶
Return True if the clause is a tautology.
A clause is always true when it contains both a literal and its negation.
Returns:
| Type | Description |
|---|---|
|
True if the clause is tautological, False otherwise. |
Source code in pishield/propositional_requirements/clause.py
resolution_on ¶
Resolve this clause with another on a given literal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
The other clause to resolve with. |
required | |
literal
|
The literal to resolve on; it and its negation are removed from the union of the two clauses. |
required |
Returns:
| Type | Description |
|---|---|
|
The resolvent Clause, or None if the resolvent is a tautology. |
Source code in pishield/propositional_requirements/clause.py
resolution ¶
Resolve this clause with another, finding a pivot literal if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
The other clause to resolve with. |
required | |
literal
|
The literal to resolve on. If None, the first literal of this
clause whose negation appears in |
None
|
Returns:
| Type | Description |
|---|---|
|
The resolvent Clause, or None if no pivot is found or the resolvent is |
|
|
a tautology. |
Source code in pishield/propositional_requirements/clause.py
always_false ¶
coherent_with ¶
Check whether predictions satisfy this clause.
A clause is satisfied when at least one of its literals is true; here this is relaxed to a probability above 0.5 for any literal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A 2D array of predicted probabilities, shape (batch, num_classes). |
required |
Returns:
| Type | Description |
|---|---|
|
A boolean array of length batch, True where the clause is satisfied. |
Source code in pishield/propositional_requirements/clause.py
is_subset ¶
Return True if this clause's literals are a subset of other's.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
The clause to test against. |
required |
Returns:
| Type | Description |
|---|---|
|
True if every literal of this clause is in |
Source code in pishield/propositional_requirements/clause.py
Clauses group¶
clauses_group ¶
Collections of propositional clauses.
A :class:ClausesGroup holds a set of :class:Clause disjunctions and provides the
machinery that turns requirements into the Shield Layer: variable elimination by
resolution, clause compaction, centrality-based ordering, and stratification into
ordered :class:ConstraintsGroup layers (optionally enforcing strong coherency).
ClausesGroup ¶
A set of clauses supporting resolution and stratification.
Attributes:
| Name | Type | Description |
|---|---|---|
clauses |
A frozenset of the :class: |
|
clauses_list |
The clauses in their original order, kept so that coherency results have a stable column order. |
Build a clauses group from an iterable of clauses.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
clauses
|
An iterable of :class: |
required |
Source code in pishield/propositional_requirements/clauses_group.py
from_constraints_group
classmethod
¶
Build a clauses group from a :class:ConstraintsGroup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
group
|
The constraints group to convert (each constraint becomes a clause). |
required |
Returns:
| Type | Description |
|---|---|
|
The equivalent ClausesGroup. |
Source code in pishield/propositional_requirements/clauses_group.py
random
classmethod
¶
Build a random clauses group, optionally filtered by coherency.
Generates up to max_clauses random clauses; if coherent_with is given,
only clauses satisfied by every one of those predictions are kept, and
generation is repeated until at least min_clauses survive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_clauses
|
The number of random clauses to generate per attempt. |
required | |
num_classes
|
The number of variables available. |
required | |
coherent_with
|
Optional array of predictions the clauses must satisfy. |
array([])
|
|
min_clauses
|
The minimum number of clauses required in the result. |
0
|
Returns:
| Type | Description |
|---|---|
|
A randomly generated ClausesGroup. |
Source code in pishield/propositional_requirements/clauses_group.py
add_detection_label ¶
Insert a detection variable at index 0 and shift the others up.
Each clause's atoms are shifted up by one and the negative literal n0 added
(so the clause is vacuously satisfied when the detection variable is off).
When forced, extra clauses tie the detection variable to every atom.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
forced
|
If True, also add |
False
|
Returns:
| Type | Description |
|---|---|
|
A new ClausesGroup including the detection variable. |
Source code in pishield/propositional_requirements/clauses_group.py
compacted ¶
Remove clauses subsumed by a smaller clause.
Sorts clauses from longest to shortest and drops any clause that is a superset of (i.e. subsumed by) a retained clause.
Returns:
| Type | Description |
|---|---|
|
A new, subsumption-free ClausesGroup. |
Source code in pishield/propositional_requirements/clauses_group.py
resolution ¶
Eliminate a variable by resolution, returning its constraints.
Splits the clauses into those containing the positive literal, the negative literal, and neither; resolves each positive against each negative clause to produce the remaining clauses (compacted), and turns the positive and negative clauses into constraints whose head is the eliminated literal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
atom
|
The variable index to eliminate. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
class: |
|
|
is the remaining :class: |
Source code in pishield/propositional_requirements/clauses_group.py
graph ¶
Build a bipartite graph linking clauses to their atoms.
Returns:
| Type | Description |
|---|---|
|
A |
|
|
an edge between each clause and every atom it mentions. |
Source code in pishield/propositional_requirements/clauses_group.py
centrality_measures
staticmethod
¶
Return the names of the supported centrality measures.
Returns:
| Type | Description |
|---|---|
|
A list of measure names usable with :meth: |
Source code in pishield/propositional_requirements/clauses_group.py
centrality ¶
Compute a centrality score per atom to guide the elimination order.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
centrality
|
The centrality measure name (one of
:meth: |
required |
Returns:
| Type | Description |
|---|---|
|
A dict mapping each graph node to its (possibly reversed) centrality score. |
Raises:
| Type | Description |
|---|---|
Exception
|
If the centrality measure name is unknown. |
Source code in pishield/propositional_requirements/clauses_group.py
stratify ¶
Convert the clauses into ordered constraint strata for the Shield Layer.
Repeatedly eliminates atoms (in an order determined by centrality) via
resolution, accumulating the resulting constraints and optionally rewriting
them to enforce strong coherency, then stratifies the accumulated constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
centrality
|
Either a centrality measure name (str) used to order atoms, an explicit iterable of atom indices giving the order, or None to use the order atoms appear in the constraints. |
required |
Returns:
| Type | Description |
|---|---|
|
A list of :class: |
|
|
meth: |
Raises:
| Type | Description |
|---|---|
Exception
|
If the clauses are unsatisfiable (clauses remain after eliminating every atom). |
Source code in pishield/propositional_requirements/clauses_group.py
coherent_with ¶
Check which clauses each prediction satisfies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A 2D array of predicted probabilities, shape (batch, num_classes). |
required |
Returns:
| Type | Description |
|---|---|
|
A boolean array of shape (batch, num_clauses), True where the corresponding |
|
|
clause is satisfied (columns in insertion order). |
Source code in pishield/propositional_requirements/clauses_group.py
atoms ¶
Return the set of all variable indices used across the clauses.
Constraint¶
constraint ¶
Propositional constraints (Horn rules).
A constraint is a Horn rule of the form head :- body, where head is a single
literal and body is a conjunction of literals: the rule states that if every body
literal holds then the head must hold. Constraints can be parsed from the head :- body
or disjunctive (y_0 or not y_1) textual forms and are the requirement representation
that the Shield Layer and Memory-efficient Loss consume.
Constraint ¶
A Horn rule head :- body over propositional literals.
Attributes:
| Name | Type | Description |
|---|---|---|
head |
The :class: |
|
body |
A frozenset of :class: |
Build a constraint from a head/body pair or from a textual rule.
Two calling conventions are supported
Constraint(head: Literal, body: Iterable[Literal])builds it directly.Constraint(text: str)parses a rule in eitherhead :- bodyform or disjunctivehead or lit or ...form (the latter parsed with reversed signs to match the:-convention).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Either two positional arguments |
()
|
Source code in pishield/propositional_requirements/constraint.py
head_encoded ¶
One-hot encode the head literal into positive and negative vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of variables (length of the encoding vectors). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
one entry is set to 1 depending on the head's atom and polarity. |
Source code in pishield/propositional_requirements/constraint.py
body_encoded ¶
Multi-hot encode the body literals into positive and negative vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of variables (length of the encoding vectors). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
marking which atoms appear positively and negatively in the body. |
Source code in pishield/propositional_requirements/constraint.py
where ¶
Differentiable select between two options.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cond
|
A 0/1 mask (or probability) selecting between the options. |
required | |
opt1
|
The value used where |
required | |
opt2
|
The value used where |
required |
Returns:
| Type | Description |
|---|---|
|
|
Source code in pishield/propositional_requirements/constraint.py
coherent_with ¶
Check whether predictions satisfy this constraint.
The body truth value is the minimum over its literals (a product/Goedel-style
conjunction); the constraint is satisfied when body <= head.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A 2D array of predicted probabilities, shape (batch, num_classes). |
required |
Returns:
| Type | Description |
|---|---|
|
A boolean array of length batch, True where the constraint is satisfied. |
Source code in pishield/propositional_requirements/constraint.py
Constraints group¶
constraints_group ¶
Collections of propositional constraints.
A :class:ConstraintsGroup bundles a set of :class:Constraint Horn rules, supports
encoding them into matrices, checking coherency of predictions, building dependency
graphs over the variables, and stratifying the constraints into ordered layers so that
each head is only resolved after the variables it depends on.
ConstraintsGroup ¶
A set of Horn constraints with encoding and stratification utilities.
Attributes:
| Name | Type | Description |
|---|---|---|
constraints |
A frozenset of the :class: |
|
constraints_list |
The constraints in their original insertion order, kept so that coherency results have a stable column order. |
Build a constraints group from a file or a list of constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
arg
|
Either a path to a constraints file (one |
required |
Source code in pishield/propositional_requirements/constraints_group.py
head_encoded ¶
Encode all constraint heads into stacked positive/negative matrices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of variables (row width of the encodings). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
constraint's head (see :meth: |
Source code in pishield/propositional_requirements/constraints_group.py
body_encoded ¶
Encode all constraint bodies into stacked positive/negative matrices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of variables (row width of the encodings). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
constraint's body (see :meth: |
Source code in pishield/propositional_requirements/constraints_group.py
encoded ¶
Encode both heads and bodies of all constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_classes
|
The number of variables (encoding width). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
returned by :meth: |
Source code in pishield/propositional_requirements/constraints_group.py
coherent_with ¶
Check which constraints each prediction satisfies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A 2D array of predicted probabilities, shape (batch, num_classes). |
required |
Returns:
| Type | Description |
|---|---|
|
A boolean array of shape (batch, num_constraints), True where the |
|
|
corresponding constraint is satisfied (columns in insertion order). |
Source code in pishield/propositional_requirements/constraints_group.py
atoms ¶
Return the set of all variable indices used across the constraints.
heads ¶
Return the set of variable indices that appear as a constraint head.
graph ¶
Build a directed dependency graph over the variables.
Adds an edge from each body atom to the head atom of every constraint, annotating it with the body and head polarities.
Returns:
| Type | Description |
|---|---|
|
A |
|
|
|
Source code in pishield/propositional_requirements/constraints_group.py
duograph ¶
Build a directed graph over signed literals (atom and its negation).
Unlike :meth:graph, each atom appears as two nodes (positive and negative
literal), and an edge is added from each body literal to the head literal.
Returns:
| Type | Description |
|---|---|
|
A |
Source code in pishield/propositional_requirements/constraints_group.py
stratify ¶
Partition the constraints into ordered dependency layers (strata).
Performs a topological-style sweep of the dependency graph: variables with no unresolved dependencies are processed first, and the constraints whose heads they are form a stratum, repeated until all variables are consumed. Each stratum can be corrected without violating an earlier one.
Returns:
| Type | Description |
|---|---|
|
A list of :class: |
|
|
that should be applied first to those applied last. |
Source code in pishield/propositional_requirements/constraints_group.py
Constraints module¶
constraints_module ¶
Differentiable correction module for one stratum of constraints.
A :class:ConstraintsModule holds the (precomputed, non-trainable) tensor encoding of a
single :class:ConstraintsGroup and corrects predictions so they satisfy that group.
Each constraint contributes a lower bound (for positive heads) or an upper bound (for
negative heads) on its head variable, derived from the truth value of its body; the
prediction is then clamped into those bounds. Two equivalent implementations are
provided: a vectorised 3D-tensor version (:meth:apply_tensor) and an iterative 2D
version (:meth:apply_iter). The Shield Layer stacks one such module per stratum.
ConstraintsModule ¶
Bases: Module
Corrects predictions to satisfy a single stratum of constraints.
The module restricts attention to the atoms occurring in its constraints (re-indexed to a minimal range) and stores the encoded heads/bodies as buffers. Bodies are evaluated with a Goedel (min) semantics and used to bound the head predictions.
Attributes:
| Name | Type | Description |
|---|---|---|
atoms |
The original variable indices covered by this module's constraints. |
|
heads |
The re-indexed head :class: |
|
pos_head, |
neg_head
|
Encoded positive/negative head indicators per constraint. |
pos_body, |
neg_body
|
Encoded positive/negative body indicators per constraint. |
symm_body, |
symm_head
|
Precomputed symmetric (-1/+1) body/head encodings. |
literals_count |
The number of literals in each constraint's body. |
Encode a constraints group into reusable correction tensors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
constraints_group
|
The :class: |
required | |
num_classes
|
The total number of variables in the full prediction space. |
required |
Source code in pishield/propositional_requirements/constraints_module.py
dimensions ¶
Return the (batch, num_atoms, num_constraints) dimensions for a tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred
|
A prediction tensor of shape (batch, num_atoms). |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
Source code in pishield/propositional_requirements/constraints_module.py
from_symmetric
staticmethod
¶
Map symmetric values in [-1, 1] back to probabilities in [0, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A tensor of symmetric values. |
required |
Returns:
| Type | Description |
|---|---|
|
The corresponding probabilities. |
Source code in pishield/propositional_requirements/constraints_module.py
to_symmetric
staticmethod
¶
Map probabilities in [0, 1] to symmetric values in [-1, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A tensor of probabilities. |
required |
Returns:
| Type | Description |
|---|---|
|
The corresponding symmetric values. |
Source code in pishield/propositional_requirements/constraints_module.py
to_minimal ¶
Restrict a full tensor to the module's atom columns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
A tensor of shape (batch, num_classes). |
required | |
atoms
|
The atom indices to keep; defaults to |
None
|
Returns:
| Type | Description |
|---|---|
|
The tensor restricted to the selected atom columns. |
Source code in pishield/propositional_requirements/constraints_module.py
from_minimal ¶
Scatter a minimal-atom tensor back into a full tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
The minimal tensor over the module's atoms. |
required | |
init
|
The full tensor to copy the values into. |
required | |
atoms
|
The atom indices the values belong to; defaults to |
None
|
Returns:
| Type | Description |
|---|---|
|
|
Source code in pishield/propositional_requirements/constraints_module.py
active_constraints ¶
Identify which constraints are activated by a goal assignment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
goal
|
A ground-truth assignment over the module's atoms. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
constraints whose body is fully satisfied by |
|
|
is unsatisfied by |
Source code in pishield/propositional_requirements/constraints_module.py
apply_tensor ¶
Correct predictions with a vectorised 3D-tensor computation.
Computes, for every constraint, the Goedel (min) truth value of its body and uses it as a lower bound on positive heads and an upper bound on negative heads, then clamps each prediction into the resulting bounds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predictions over the module's atoms, shape (batch, num_atoms). |
required | |
active_constraints
|
Optional per-constraint mask zeroing inactive constraints' contributions. |
None
|
|
body_mask
|
Optional per-atom mask used to drop body literals that the goal already determines. |
None
|
Returns:
| Type | Description |
|---|---|
|
The corrected predictions, same shape as |
Source code in pishield/propositional_requirements/constraints_module.py
apply_iter ¶
Correct predictions by iterating constraint by constraint with 2D matrices.
Equivalent to :meth:apply_tensor but loops over constraints, accumulating per
atom lower/upper bounds; this avoids materialising the large 3D tensors. Can
accept incoming bounds and/or return the raw bounds instead of corrected
predictions, which the goal-conditioned path uses to chain two passes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predictions over the module's atoms, shape (batch, num_atoms). |
required | |
active_constraints
|
Optional per-constraint mask zeroing inactive constraints' contributions. |
None
|
|
body_mask
|
Optional per-atom mask used to drop body literals. |
None
|
|
in_bounds
|
Optional |
None
|
|
out_bounds
|
If True, return the raw |
False
|
Returns:
| Type | Description |
|---|---|
|
Either the corrected predictions, or the |
|
|
|
Source code in pishield/propositional_requirements/constraints_module.py
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | |
apply ¶
Correct predictions using the chosen implementation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predictions over the module's atoms. |
required | |
iterative
|
If True use :meth: |
required |
Returns:
| Type | Description |
|---|---|
|
The corrected predictions. |
Source code in pishield/propositional_requirements/constraints_module.py
apply_goal ¶
Correct predictions consistently with a known goal assignment.
Applies the constraints in two passes: first using only constraints whose body is fully satisfied by the goal (to propagate firm consequences), then using the constraints whose head is unsatisfied with the goal-determined body literals masked out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The predictions over the module's atoms. |
required | |
goal
|
The goal (ground-truth) assignment over the module's atoms. |
required | |
iterative
|
If True use the iterative implementation, else the tensor one. |
required |
Returns:
| Type | Description |
|---|---|
|
The corrected predictions. |
Source code in pishield/propositional_requirements/constraints_module.py
forward ¶
Correct a full prediction tensor against this stratum's constraints.
Restricts the predictions to the module's atoms, applies the correction (optionally goal-conditioned), and scatters the result back into the full tensor. Returns the input unchanged when there are no predictions or no atoms.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The full prediction tensor, shape (batch, num_classes). |
required | |
goal
|
Optional goal assignment over the full variable space; when given, corrections are made consistent with it. |
None
|
|
iterative
|
If True use the iterative implementation, else the tensor one. |
True
|
Returns:
| Type | Description |
|---|---|
|
The full prediction tensor with this stratum's atoms corrected. |
Source code in pishield/propositional_requirements/constraints_module.py
run_cm ¶
Run a constraints module both ways and assert they agree.
Runs the module with the iterative and tensor implementations and checks the results are numerically close; mainly a testing/debugging helper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cm
|
The :class: |
required | |
preds
|
The prediction tensor. |
required | |
goal
|
Optional goal assignment. |
None
|
|
device
|
The torch device to run on. |
'cpu'
|
Returns:
| Type | Description |
|---|---|
|
The corrected predictions (from the iterative implementation), on CPU. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the two implementations disagree. |
Source code in pishield/propositional_requirements/constraints_module.py
Strong coherency¶
strong_coherency ¶
Strong-coherency preprocessing of constraints.
When several constraints share the same head (some asserting it positively, some negatively), the Shield Layer must correct that head consistently. This module rewrites such constraint sets so that the positive and negative rules branch on a common body literal, which guarantees a strongly coherent correction. The shared literal is chosen as the highest-ranking atom (per the variable ordering) appearing in the rule bodies.
get_max_ranking_atom ¶
Find the atom with the smallest position in the ranking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
atoms_list
|
The candidate atom indices. |
required | |
ranking
|
An ordered sequence of atoms; earlier means higher priority. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
|
Source code in pishield/propositional_requirements/strong_coherency.py
create_new_rule ¶
Return a copy of a rule with one extra literal added to its body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rule
|
The :class: |
required | |
extra_literal
|
The atom index of the literal to add. |
required | |
positive
|
The polarity of the added literal. |
required |
Returns:
| Type | Description |
|---|---|
|
A new :class: |
Source code in pishield/propositional_requirements/strong_coherency.py
get_max_ranking_eligible_atom_from_sets_of_rules ¶
Pick the highest-ranked body atom across two rule sets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
R
|
A list of constraints (e.g. the positive-head rules). |
required | |
R_other
|
Another list of constraints (e.g. the negative-head rules). |
required | |
literal_ranking
|
The ordering used to rank atoms. |
required |
Returns:
| Type | Description |
|---|---|
|
The atom index of the highest-ranked body literal occurring in either set, or |
|
|
None if neither set has any body literals. |
Source code in pishield/propositional_requirements/strong_coherency.py
extend_rules_set ¶
Branch every rule on the chosen literal unless it already contains it.
For each rule that does not already mention max_ranking_body_literal, two new
rules are produced (with the literal added positively and negatively); rules that
already contain the literal (in either polarity) are kept unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
R
|
The list of constraints (all sharing the same head) to extend. |
required | |
max_ranking_body_literal
|
The atom index to branch the rules on. |
required |
Returns:
| Type | Description |
|---|---|
|
A list of the extended constraints. |
Source code in pishield/propositional_requirements/strong_coherency.py
strong_coherency_constraint_preprocessing ¶
Rewrite a head's constraints to guarantee a strongly coherent correction.
Splits the constraints for one head into those asserting it positively and those asserting it negatively, picks the highest-ranked shared body atom, and branches both groups on that atom so the head can be corrected consistently.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
R_atom
|
The list of constraints sharing the same head atom. |
required | |
literal_ranking
|
The variable ordering used to choose the branching atom. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
class: |
|
|
eligible shared body atom exists. |
Source code in pishield/propositional_requirements/strong_coherency.py
Detection threshold¶
detection_threshold ¶
Detection-threshold based slicing of predictions.
A detection variable (at column 0) gates whether an example is processed: only rows
whose detection probability exceeds a threshold are kept (cut) before the
requirements are applied, and the corrected rows are then scattered back into the
original tensor (uncut).
DetectionThreshold ¶
Restrict prediction rows to those passing a detection threshold.
Attributes:
| Name | Type | Description |
|---|---|---|
threshold |
The minimum value of the detection variable (column 0) for a row to be kept. |
Store the detection threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
threshold
|
The minimum detection probability for a row to be kept. |
required |
Source code in pishield/propositional_requirements/detection_threshold.py
cut ¶
Drop the detection column and keep only masked rows.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
The full prediction tensor, shape (batch, num_classes). |
required | |
mask
|
A boolean row mask selecting which examples to keep. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple of the sliced predictions (kept rows, columns from index 1 |
|
|
onward) and a callable that scatters updated values back via :meth: |
Source code in pishield/propositional_requirements/detection_threshold.py
uncut ¶
Scatter corrected rows back into the original tensor.
Re-attaches the detection column and writes the corrected rows back into the
positions selected by mask, leaving non-selected rows untouched.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
init
|
The original full prediction tensor before cutting. |
required | |
mask
|
The boolean row mask used by :meth: |
required | |
preds
|
The corrected predictions for the kept rows (without column 0). |
required |
Returns:
| Type | Description |
|---|---|
|
A tensor the shape of |
Source code in pishield/propositional_requirements/detection_threshold.py
cutter ¶
Build a cut function for predictions using the detection threshold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
preds
|
A prediction tensor whose column 0 is the detection variable. |
required |
Returns:
| Type | Description |
|---|---|
|
A callable mapping a prediction tensor to the result of :meth: |
|
|
a row mask derived from this tensor's detection column. |
Source code in pishield/propositional_requirements/detection_threshold.py
Slicer¶
slicer ¶
Partial application of the Shield Layer.
The Slicer lets the Shield Layer apply only a prefix of its stratified correction modules to a subset of the variables (atoms), which is used to gradually enable the requirements during training.
Slicer ¶
Selects a subset of atoms and a prefix of correction modules.
Attributes:
| Name | Type | Description |
|---|---|---|
atoms |
The list of variable (atom) indices the slicer restricts to. |
|
modules |
The number of leading correction modules to keep. |
Store the atoms and module count to slice to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
atoms
|
An iterable of variable indices to keep. |
required | |
modules
|
The number of leading correction modules to keep. |
required |
Source code in pishield/propositional_requirements/slicer.py
slice_atoms ¶
Select the slicer's columns from a tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tensor
|
A 2D tensor indexed by variable in its columns. |
required |
Returns:
| Type | Description |
|---|---|
|
The tensor restricted to the slicer's atom columns. |
Source code in pishield/propositional_requirements/slicer.py
slice_modules ¶
Return the leading prefix of correction modules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
modules
|
The full ordered sequence of correction modules. |
required |
Returns:
| Type | Description |
|---|---|
|
The first |
Source code in pishield/propositional_requirements/slicer.py
Profiler¶
profiler ¶
Lightweight time and GPU-memory profiling.
Provides a hierarchical profiler used to instrument the constraint modules: named
"watches" (context managers, or the :meth:Profiler.wrap decorator) record the elapsed
time and peak/net CUDA memory of code regions, aggregating the measurements into a tree
of :class:Stats. On CPU-only systems the memory measurements degrade to zero.
MaxStack ¶
A stack whose update raises stored values to a running maximum.
Supports the usual push/pop plus an update(x) that bumps the top of stack up to
x; popping a value also propagates it into the new top, so nested peak measures
accumulate correctly.
Attributes:
| Name | Type | Description |
|---|---|---|
stack |
The underlying list of values. |
Initialise an empty stack.
Source code in pishield/propositional_requirements/profiler.py
push ¶
Push a value onto the stack.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
The value to push. |
required |
update ¶
Raise the top of the stack to at least value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
The lower bound to apply to the current top (no-op if empty). |
required |
Source code in pishield/propositional_requirements/profiler.py
pop ¶
Pop the top value, propagating it into the new top as a maximum.
Returns:
| Type | Description |
|---|---|
|
The popped value. |
Source code in pishield/propositional_requirements/profiler.py
PeakMemoryManager ¶
Singleton tracking nested peak CUDA-memory measurements.
Uses a :class:MaxStack so that entering a region resets the CUDA peak counter and
exiting returns the peak observed within that region, while still propagating it to
enclosing regions.
Attributes:
| Name | Type | Description |
|---|---|---|
stack |
The :class: |
Initialise with an empty measurement stack.
Source code in pishield/propositional_requirements/profiler.py
Stats ¶
Aggregated time and memory statistics for a profiled region.
Attributes:
| Name | Type | Description |
|---|---|---|
peak |
The maximum peak memory observed. |
|
diff |
The maximum net memory change observed. |
|
sum |
The summed net memory change across measurements. |
|
tdiff |
The maximum elapsed time observed. |
|
tsum |
The summed elapsed time across measurements. |
Store the individual statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
peak
|
The peak memory. |
required | |
diff
|
The net memory change. |
required | |
sum
|
The summed net memory change. |
required | |
tdiff
|
The elapsed time. |
required | |
tsum
|
The summed elapsed time. |
required |
Source code in pishield/propositional_requirements/profiler.py
single
classmethod
¶
Build a Stats from a single measurement (sum equals the value).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
peak
|
The peak memory. |
required | |
diff
|
The net memory change. |
required | |
tdiff
|
The elapsed time. |
required |
Returns:
| Type | Description |
|---|---|
|
A Stats whose sum fields equal the corresponding single values. |
Source code in pishield/propositional_requirements/profiler.py
null
classmethod
¶
memory ¶
Return the memory statistics as a tuple.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
long
|
If True include the summed change; otherwise only peak and diff. |
True
|
Returns:
| Type | Description |
|---|---|
|
|
Source code in pishield/propositional_requirements/profiler.py
time ¶
Return the timing statistics as a tuple.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
long
|
If True include the summed time; otherwise only the max. |
True
|
Returns:
| Type | Description |
|---|---|
|
|
Source code in pishield/propositional_requirements/profiler.py
tuple ¶
Return the combined time and memory statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
long
|
Whether to include the summed fields. |
True
|
Returns:
| Type | Description |
|---|---|
|
A tuple |
Source code in pishield/propositional_requirements/profiler.py
Profiler ¶
Hierarchical recorder of timing and memory statistics.
A profiler owns a tree of named "watches"; each leaf accumulates a list of
:class:Stats. Sub-profilers created via :meth:branch share the parent's
subtree, allowing nested instrumentation. Profiling can be globally toggled with
:meth:enable/:meth:disable.
Attributes:
| Name | Type | Description |
|---|---|---|
watches |
The nested dict of recorded watches (subtrees or lists of Stats). |
|
manager |
The shared :class: |
Create a profiler over an optional existing watches subtree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
watches
|
An existing watches dict to attach to, or None for a fresh tree. |
None
|
Source code in pishield/propositional_requirements/profiler.py
enable
classmethod
¶
disable
classmethod
¶
enabled
classmethod
¶
shared
classmethod
¶
norm
staticmethod
¶
Convert a byte count to mebibytes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
A value in bytes. |
required |
Returns:
| Type | Description |
|---|---|
|
The value in MiB. |
branch ¶
Return a sub-profiler for a named subtree, creating it if needed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
The name of the branch. |
required |
Returns:
| Type | Description |
|---|---|
|
A Profiler scoped to the named subtree. |
Source code in pishield/propositional_requirements/profiler.py
register ¶
Record one measurement under a named watch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
The watch name. |
required | |
peak
|
The peak memory in bytes. |
required | |
diff
|
The net memory change in bytes. |
required | |
tdiff
|
The elapsed time in seconds. |
required |
Source code in pishield/propositional_requirements/profiler.py
watch ¶
Return a context manager that times and measures a named region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
The watch name to record under. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
A |
class: |
Source code in pishield/propositional_requirements/profiler.py
wrap ¶
Decorator that profiles a function under its own name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
The function to wrap. |
required |
Returns:
| Type | Description |
|---|---|
|
The wrapped function, profiled under |
Source code in pishield/propositional_requirements/profiler.py
map_dict
classmethod
¶
Recursively apply a function to every leaf of a nested dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f
|
The function applied to each non-dict leaf value. |
required | |
node
|
The nested dict to traverse. |
required |
Returns:
| Type | Description |
|---|---|
|
A new nested dict with |
Source code in pishield/propositional_requirements/profiler.py
reset ¶
Clear all recorded measurements, leaving a single null Stats per watch.
get_kind ¶
Return a selector mapping a Stats to the requested view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
One of |
required | |
long
|
Whether the returned tuples should include the summed fields. |
required |
Returns:
| Type | Description |
|---|---|
|
A callable mapping a :class: |
Raises:
| Type | Description |
|---|---|
Exception
|
If |
Source code in pishield/propositional_requirements/profiler.py
all ¶
Return every individual measurement per watch.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
The view to extract (see :meth: |
'all'
|
Returns:
| Type | Description |
|---|---|
|
A nested dict mapping each watch to the list of its per-measurement tuples. |
Source code in pishield/propositional_requirements/profiler.py
combined ¶
Return the per-watch aggregate of all its measurements.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
The view to extract (see :meth: |
'all'
|
Returns:
| Type | Description |
|---|---|
|
A nested dict mapping each watch to its combined Stats tuple. |
Source code in pishield/propositional_requirements/profiler.py
total ¶
Return the aggregate over every watch in the tree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
The view to extract (see :meth: |
'all'
|
Returns:
| Type | Description |
|---|---|
|
The combined Stats tuple summed across all watches. |
Source code in pishield/propositional_requirements/profiler.py
Watch ¶
Context manager that records the time and memory of its body.
On enter it snapshots the time and allocated memory; on exit it computes the elapsed time, net memory change and peak memory and registers them with the profiler. Both methods are no-ops when profiling is disabled.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
The watch name to register under. |
|
profiler |
The owning :class: |
Store the watch name and owning profiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
The watch name. |
required | |
profiler
|
The owning Profiler. |
required |
Source code in pishield/propositional_requirements/profiler.py
singleton ¶
Class decorator that turns a class into a lazily-created singleton.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
The class to wrap. |
required |
Returns:
| Type | Description |
|---|---|
|
A constructor function that always returns the single shared instance. |
Source code in pishield/propositional_requirements/profiler.py
no_cuda ¶
get_allocated ¶
Return the currently allocated CUDA memory in bytes (0 without CUDA).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device
|
Optional CUDA device. |
None
|
Returns:
| Type | Description |
|---|---|
|
The allocated memory in bytes, or 0 if CUDA is unavailable. |
Source code in pishield/propositional_requirements/profiler.py
get_peak ¶
Return the peak allocated CUDA memory in bytes (0 without CUDA).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device
|
Optional CUDA device. |
None
|
Returns:
| Type | Description |
|---|---|
|
The peak allocated memory in bytes, or 0 if CUDA is unavailable. |
Source code in pishield/propositional_requirements/profiler.py
reset_peak ¶
Reset the CUDA peak-memory statistics (no-op without CUDA).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device
|
Optional CUDA device. |
None
|
condition ¶
Build a decorator that only runs the wrapped function when a condition holds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cond
|
A boolean, or a callable returning a boolean, evaluated on each call. |
required |
Returns:
| Type | Description |
|---|---|
|
A decorator that runs the function when the condition is truthy, else returns |
|
|
None. |
Source code in pishield/propositional_requirements/profiler.py
Utilities¶
util ¶
Training, evaluation and ordering utilities for propositional requirements.
Helper routines used in examples and experiments: a standard PyTorch training loop and test loop that run predictions through a Shield Layer, a function for visualising the class predictions of a 2D model, and a helper for resolving the variable ordering / centrality used to stratify the requirements.
train ¶
Run one training epoch with predictions corrected by the Shield Layer.
For each batch, the model's predictions are passed through clayer (with the
ground-truth labels as goal and a slicer that gradually enables the requirements),
then the loss is computed on the sliced atoms and backpropagated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataloader
|
A PyTorch DataLoader yielding |
required | |
model
|
The prediction model. |
required | |
clayer
|
The Shield Layer correcting the predictions. |
required | |
loss_fn
|
The loss function applied to corrected predictions and labels. |
required | |
optimizer
|
The optimizer updating the model parameters. |
required | |
device
|
The torch device to run on. |
required | |
ratio
|
The fraction of strata to enable via the layer's slicer (1.0 = all). |
1.0
|
Source code in pishield/propositional_requirements/util.py
test ¶
Evaluate the model with Shield-Layer-corrected predictions.
Runs the model over the dataloader (no goal), corrects the predictions with
clayer, and reports the average loss and per-class accuracy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataloader
|
A PyTorch DataLoader yielding |
required | |
model
|
The prediction model. |
required | |
clayer
|
The Shield Layer correcting the predictions. |
required | |
loss_fn
|
The loss function. |
required | |
device
|
The torch device to run on. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple |
|
|
accuracy percentages. |
Source code in pishield/propositional_requirements/util.py
draw_classes ¶
Plot each class score of a model over the unit square.
Evaluates the model on a dense grid of points in [0, 1)^2 and renders one
filled-contour subplot per output class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
A model mapping 2D points to per-class scores. |
required | |
draw
|
Optional callable |
None
|
|
path
|
Optional file path to save the figure to. |
None
|
|
device
|
The torch device to run the model on. |
'cpu'
|
|
show
|
If True, display the figure interactively. |
False
|
Returns:
| Type | Description |
|---|---|
|
The matplotlib Figure that was created. |
Source code in pishield/propositional_requirements/util.py
get_order_and_centrality ¶
Resolve the centrality/ordering argument used to stratify the requirements.
If a custom ordering is supplied and the choice is a custom/given one, the ordering
is parsed into an explicit array of atom indices (reversed when the choice contains
'rev'); otherwise the named centrality choice is returned as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ordering_choice
|
str
|
The ordering choice name (e.g. a centrality measure, or one
containing |
required |
custom_ordering
|
str
|
An optional comma-separated string of atom indices. |
required |
Returns:
| Type | Description |
|---|---|
|
Either the ordering choice name (str) or an array of atom indices giving an |
|
|
explicit order. |