Skip to content

Add ArbitraryConstraint for general structural constraints#143

Open
ryan112358 wants to merge 1 commit into
masterfrom
arbitrary-constraint
Open

Add ArbitraryConstraint for general structural constraints#143
ryan112358 wants to merge 1 commit into
masterfrom
arbitrary-constraint

Conversation

@ryan112358

Copy link
Copy Markdown
Owner

Adds ArbitraryConstraint to extensions/constraints.py alongside the existing DeterministicConstraint. The two are complementary siblings:

DeterministicConstraint ArbitraryConstraint
Expressiveness Many-to-one only Arbitrary
Message passing O( fine
Use when Functional dependencies Conditional / universe constraints

API

# From valid combinations
c = ArbitraryConstraint(
    attributes=('gqtype', 'gq'),
    valid=np.array([[0, 0], [0, 1], [1, 3], [2, 3], ...]),
)

# From invalid combinations (complement)
c = ArbitraryConstraint(
    attributes=('sex', 'chborn'),
    invalid=np.array([[0, 1], [0, 2], ...]),  # males can't have children born
)

# From a deterministic mapping
c = ArbitraryConstraint.from_mapping('bpld', 'bpl', mapping_array)

# Get the constraint potential
factor = c.as_potential(domain)

Exactly one of valid or invalid must be specified. Supports any number of attributes.

Motivation

The census domain has 14 cross-attribute constraints. 13 are functional dependencies handled by DeterministicConstraint, but gqtype ↔ gq is a conditional constraint (one-to-many in both directions). This class fills that gap.

Tests

18 unit tests covering construction, validation, both potential modes, complementarity, from_mapping equivalence, message passing integration, and equality semantics.

@ryan112358 ryan112358 force-pushed the arbitrary-constraint branch from 9a02c56 to c10c7db Compare June 23, 2026 14:22
Add ArbitraryConstraint to extensions/constraints.py for arbitrary
cross-attribute constraints via allowed or disallowed index combinations.
Unlike DeterministicConstraint (many-to-one only, O(|fine|) routing),
this produces a dense -inf/0 log-space factor for standard inference.

- Construct from valid OR invalid combinations (exactly one required)
- Supports any number of attributes
- from_mapping() classmethod bridges to DeterministicConstraint patterns
- as_potential(domain) produces the constraint Factor
- Both constrained_shafer_shenoy and constrained_implicit accept mixed
  tuples of DeterministicConstraint and ArbitraryConstraint; arbitrary
  constraints are folded into potentials before inference

Tested: 21 new unit tests + full suite (1108 tests pass).
@ryan112358 ryan112358 force-pushed the arbitrary-constraint branch from c10c7db to b5003fd Compare June 23, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant