Common errors

This page lists common validation failures, their exact messages, and the corresponding fixes. The package-specific exception hierarchy is defined in evidencelib.exceptions.

Catching package-specific errors

EvidenceLibError is the base class for exceptions defined by the package. It is not raised directly. Catch it when one handler should cover both invalid mass assignments and undefined total-conflict normalization.

from evidencelib import Frame
from evidencelib.exceptions import EvidenceLibError

frame = Frame.dst(["A", "B"])

try:
    frame.mass({"A": 0.5, "B": 0.25})
except EvidenceLibError as error:
    print(error)

Errors caused by incompatible frames, proposition syntax, or invalid argument shapes are standard ValueError or TypeError exceptions.

InvalidMassError: masses do not sum to one

from evidencelib import Frame

frame = Frame.dst(["A", "B"])
mass = frame.mass({"A": 0.5, "B": 0.25})

Message:

Mass values must sum to 1.0, got 0.75.

Fix the source values so they sum to one. Assign any unresolved support to the total frame rather than silently renormalizing elicited data.

mass = frame.mass({"A": 0.5, "B": 0.25, "A|B": 0.25})

InvalidMassError is also raised for negative, infinite, or NaN masses.

TotalConflictError: Dempster normalization is undefined

from evidencelib import Frame

frame = Frame.dst(["A", "B"])
A, B = frame.symbols()

first = frame.mass({A: 1.0})
second = frame.mass({B: 1.0})
first.dempster(second)

Message:

Dempster normalization is undefined at total conflict.

Dempster’s rule cannot divide by the remaining non-conflicting mass when that mass is zero. Inspect the conflict with first.smets(second), or select a rule whose conflict treatment matches the application, such as yager(), dubois_prade(), or pcr5().

Proposition outside the frame

frame = Frame.dst(["A", "B"])
frame.mass({"C": 1.0})

Message:

Could not parse proposition 'C'

Use only atom names declared in the frame. If C is a real hypothesis, create a new frame containing it and reconstruct all source mass functions on that frame.

Invalid exclusive constraint

Frame.hybrid(["A", "B"], exclusive=["A", "B"])

Message:

exclusive groups must be sequences of atom names, not strings.

Each group must itself be a sequence. Use a tuple inside the outer list:

Frame.hybrid(["A", "B"], exclusive=[("A", "B")])

The equivalent symbolic form is Frame.hybrid(["A", "B"], empty=["A&B"]).

Mass already assigned to the empty proposition

frame = Frame.dst(["A", "B"])
A, B = frame.symbols()

conflicted = frame.mass({frame.empty: 0.1, A: 0.9})
other = frame.mass({A | B: 1.0})
conflicted.dsmh(other)

Message:

DSmH cannot recover the origin of mass already collapsed onto empty. Create sources on their original frame and pass the constrained target explicitly with dsmh(..., model=target_frame).

DSmH must know which focal propositions produced a forbidden intersection. Keep the original source assignments and pass a constrained target model to dsmh() instead of using a source in which that provenance has already been collapsed onto empty.

Mixing different frame instances

left = Frame.dst(["A", "B"])
right = Frame.dst(["A", "B"])

left.mass({"A": 1.0}).dempster(right.mass({"A": 1.0}))

Message:

All mass functions must belong to the same frame.

Matching atom names are not sufficient. Reuse one Frame instance for every source that will be fused.

A target model relaxes source constraints

source = Frame.dst(["A", "B"])
target = Frame.dsmt(["A", "B"])

first = source.mass({"A": 1.0})
second = source.mass({"A|B": 1.0})
first.dsmh(second, model=target)

Message:

The DSmH target model may add constraints but cannot make regions possible that were absent from the source frame.

A target model may remove possible regions, but it cannot reconstruct overlap that the source frame never represented. Build the sources on a free DSm frame before applying a more constrained hybrid target.