Skip to content

gh-36265: Raise ValueError early in Bijectionist.set_value_restrictions() when restriction is empty - #42700

Open
Chaitanya140904 wants to merge 2 commits into
sagemath:developfrom
Chaitanya140904:gh-36265-bijectionist-early-value-restriction-error
Open

gh-36265: Raise ValueError early in Bijectionist.set_value_restrictions() when restriction is empty#42700
Chaitanya140904 wants to merge 2 commits into
sagemath:developfrom
Chaitanya140904:gh-36265-bijectionist-early-value-restriction-error

Conversation

@Chaitanya140904

Copy link
Copy Markdown
Contributor

Description

Bijectionist.set_value_restrictions() accepted value restrictions that produced an
empty intersection with Z without complaint. The ValueError was only raised much
later — deep inside _compute_possible_block_values() when solutions_iterator() was
already running — making it very hard to trace back to the original typo.

What problem does this solve?

# Before this fix — error fires only when iterating solutions
sage: A = [1, 2, 3]
sage: b = Bijectionist(A, A)
sage: b.set_value_restrictions((1, [4]))   # silently accepted
sage: next(b.solutions_iterator())         # error raised here, far from the typo
...
ValueError: no possible values found for singleton block [1]

A second common pitfall: passing a tuple of values instead of a list
(iterables as elements make this especially confusing):

sage: A = [(1, 2), (3, 4)]
sage: b = Bijectionist(A, A)
sage: b.set_value_restrictions(((1, 2), (3, 4)))  # (3, 4) treated as iterable of values

### How it is fixed

`set_value_restrictions()` now checks the intersection immediately and raises a
descriptive `ValueError` right at the point of the mistake:

```python
# After this fix
sage: A = [1, 2, 3]
sage: b = Bijectionist(A, A)
sage: b.set_value_restrictions((1, [4]))
Traceback (most recent call last):
...
ValueError: the value restriction for element 1 is empty:
none of the given values [4] lie in Z = {1, 2, 3}

…ner product matrix

The norm() method on free module elements was computing the standard
Euclidean norm regardless of whether the parent had a non-trivial inner
product matrix. This caused inconsistency for IntegralLattice vectors:

  sage: L = IntegralLattice(matrix([[1000,0],[0,1]]))
  sage: v = L.0
  sage: v.norm()        # was 1 (wrong — Euclidean norm)
  sage: v.inner_product(v)  # was 1000 (correct)

Fix: when p=2 and the parent has a non-identity inner product matrix,
use inner_product(self) for the norm computation, so that
norm()^2 == inner_product(self, self) consistently.

Fixes: sagemath#38543
…en restriction is empty

Previously, Bijectionist.set_value_restrictions() silently stored an empty
intersection when none of the specified values appeared in Z, only raising
a ValueError later when _compute_possible_block_values() was called (i.e.
during solutions_iterator()). This made it hard to catch typos.

This commit raises a descriptive ValueError immediately in
set_value_restrictions() when the intersection of the given values with Z
is empty, giving the user an actionable message right away:

    ValueError: the value restriction for element 1 is empty:
    none of the given values [4] lie in Z = {1, 2, 3}

This also catches the common iterable-element mistake of passing a tuple
of allowed values instead of a list (e.g. set_value_restrictions((a, (v1,v2)))
instead of set_value_restrictions((a, [v1, v2]))).

Updated docstring with two new EXAMPLES and updated TESTS to reflect the
new (earlier) error point. The _compute_possible_block_values() test is
updated to bypass the public API directly, since the old test case no
longer reaches that method.

Fixes sagemath#36265
@mantepse

Copy link
Copy Markdown
Contributor

I like your change to bijectionist.py, but there are two files that do not belong to the commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants