Skip to content

gh-36531: Add preimage/inverse_image methods to Polyhedron_base5 - #42619

Open
Chaitanya140904 wants to merge 2 commits into
sagemath:developfrom
Chaitanya140904:polyhedron-preimage
Open

gh-36531: Add preimage/inverse_image methods to Polyhedron_base5#42619
Chaitanya140904 wants to merge 2 commits into
sagemath:developfrom
Chaitanya140904:polyhedron-preimage

Conversation

@Chaitanya140904

Copy link
Copy Markdown
Contributor

This PR implements the feature requested in #36531 by adding two new methods
to Polyhedron_base5:

  • preimage(linear_transf, new_base_ring=None)
  • inverse_image(linear_transf, new_base_ring=None) (alias for preimage)

What problem does this solve?

Previously, SageMath provided linear_transformation to compute the image
of a polyhedron under a linear map f(x) = T·x. However, there was no method
to compute the preimage (inverse image) — i.e., given a polyhedron
Q ⊆ ℝᵐ and a linear map f : ℝⁿ → ℝᵐ, compute:

f⁻¹(Q) = { x ∈ ℝⁿ : f(x) ∈ Q }

This fills the gap and complements the existing ConvexSet_base.linear_transformation API.

How it works

Given the H-representation of Q:

Q = { y ∈ ℝᵐ : A·y ≤ b,  C·y = d }

and a linear map f(x) = T·x where T is an (m × n) matrix,
substituting y = T·x gives directly:

f⁻¹(Q) = { x ∈ ℝⁿ : (A·T)·x ≤ b,  (C·T)·x = d }

This is a valid H-representation of a polyhedron in ℝⁿ and is constructed
directly from the H-representation without any V-representation conversion.

Changes

src/sage/geometry/polyhedron/base5.py

  • Added preimage(linear_transf, new_base_ring=None) with:
    • Full r""" docstring including a LaTeX .. MATH:: block showing the preimage formula
    • INPUT section documenting the matrix shape (m × n) where m = self.ambient_dim()
    • EXAMPLES:: block with 5 examples: half-space preimage, projection, scalar dilation, empty polyhedron, alias check
    • TESTS:: block covering: ambient dim correctness, base ring check, ValueError for incompatible matrix shape, backend preservation
    • .. SEEALSO:: links to linear_transformation and inverse_image
  • Added inverse_image(linear_transf, new_base_ring=None) as a documented alias for preimage,
    with its own docstring, examples, and .. SEEALSO:: links
  • Updated linear_transformation's .. SEEALSO:: to cross-link preimage

Fixes #36531

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Documentation preview for this PR (built with commit 1eef6d6; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@cxzhong

cxzhong commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Can you rebase to lastest develop

Adds two new methods to compute the preimage of a polyhedron
under a linear map f: R^n -> R^m:

- preimage(linear_transf, new_base_ring=None)
- inverse_image(linear_transf, new_base_ring=None) [alias]

Given Q = {y : Ay <= b} and f(x) = T*x, the preimage is
{x : (A*T)x <= b}, constructed directly from the H-representation.

Also cross-links preimage in linear_transformation's SEEALSO.

Fixes: sagemath#36531
- Fix first example output: P.preimage(A) returns QQ^2 with
  1 vertex, 1 ray, 1 line (not ZZ^2 with 2 rays)
- Fix projection example: matrix must have nrows == ambient_dim;
  use T = matrix([[1],[0]]) mapping R^1 -> R^2 instead of
  proj = matrix([[1,0]]) which has wrong shape
- Fix Q.base_ring() expected output: returns Rational Field
  not Integer Ring due to base_extend normalization
@Chaitanya140904

Copy link
Copy Markdown
Contributor Author

Done, rebased onto latest develop

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.

Polyhedron: Add preimage (inverse_image) method

2 participants