Skip to content

Commit

Permalink
New row order parameter for polyhedron_from_matrix.
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmtroffaes committed Sep 17, 2024
1 parent e4ea355 commit 219b845
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ Fully detailed changes:

* The Fourier and block elimination functions are now exposed (see issue #38).

* You can now specify the row order type
when constructing a ``Polyhedron`` from a matrix.
(This exposes the ``dd_DDMatrix2Poly2`` function.)

* Thanks to the reorganization, there now is a standalone Python package that
installs just the floating point interface without needing the gmp or cddlib
libraries installed.
Expand Down
17 changes: 14 additions & 3 deletions cython/pycddlib.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -544,15 +544,26 @@ cdef polyhedron_from_ptr(dd_PolyhedraPtr dd_poly):
return poly


def polyhedron_from_matrix(mat: Matrix) -> Polyhedron:
"""Run the double description method to convert *mat* into a polyhedron."""
def polyhedron_from_matrix(
mat: Matrix, row_order_type: Optional[RowOrderType] = None
) -> Polyhedron:
"""Run the double description method to convert *mat* into a polyhedron,
using *row_order_type* if specified.

.. versionadded:: 3.0.0

The *row_order_type* parameter.
"""
if (
mat.dd_mat.representation != dd_Inequality
and mat.dd_mat.representation != dd_Generator
):
raise ValueError("rep_type must be INEQUALITY or GENERATOR")
cdef dd_ErrorType error = dd_NoError
dd_poly = dd_DDMatrix2Poly(mat.dd_mat, &error)
if row_order_type is None:
dd_poly = dd_DDMatrix2Poly(mat.dd_mat, &error)
else:
dd_poly = dd_DDMatrix2Poly2(mat.dd_mat, row_order_type, &error)
if error != dd_NoError:
dd_FreePolyhedra(dd_poly)
_raise_error(error, "failed to run double description method")
Expand Down
3 changes: 2 additions & 1 deletion cython/pyenums.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class RepType(IntEnum):
INEQUALITY = dd_Inequality
GENERATOR = dd_Generator

class _RowOrderType(IntEnum):
class RowOrderType(IntEnum):
"""Type of row order to use in the double description method."""
MAX_INDEX = dd_MaxIndex
MIN_INDEX = dd_MinIndex
MIN_CUTOFF = dd_MinCutoff
Expand Down
14 changes: 14 additions & 0 deletions docs/source/cdd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ Enums
INEQUALITY
GENERATOR

.. autoclass:: RowOrderType(value)
:show-inheritance:

.. attribute::
MAX_INDEX
MIN_INDEX
MIN_CUTOFF
MAX_CUTOFF
MIX_CUTOFF
LEX_MIN
LEX_MAX
RANDOM_ROW


Classes
-------

Expand Down
14 changes: 13 additions & 1 deletion src/cdd/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ class RepType(enum.IntEnum):
INEQUALITY: ClassVar[RepType] = ...
UNSPECIFIED: ClassVar[RepType] = ...

class RowOrderType(enum.IntEnum):
MAX_INDEX: ClassVar[RowOrderType] = ...
MIN_INDEX: ClassVar[RowOrderType] = ...
MIN_CUTOFF: ClassVar[RowOrderType] = ...
MAX_CUTOFF: ClassVar[RowOrderType] = ...
MIX_CUTOFF: ClassVar[RowOrderType] = ...
LEX_MIN: ClassVar[RowOrderType] = ...
LEX_MAX: ClassVar[RowOrderType] = ...
RANDOM_ROW: ClassVar[RowOrderType] = ...

def block_elimination(mat: Matrix, col_set: Container[int]) -> Matrix: ...
def copy_adjacency(poly: Polyhedron) -> Sequence[Set[int]]: ...
def copy_generators(poly: Polyhedron) -> Matrix: ...
Expand Down Expand Up @@ -98,4 +108,6 @@ def matrix_from_array(
obj_type: LPObjType = LPObjType.NONE,
obj_func: Optional[Sequence[SupportsNumberType]] = None,
) -> Matrix: ...
def polyhedron_from_matrix(mat: Matrix) -> Polyhedron: ...
def polyhedron_from_matrix(
mat: Matrix, row_order_type: Optional[RowOrderType] = None
) -> Polyhedron: ...
6 changes: 4 additions & 2 deletions src/cdd/gmp.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from collections.abc import Container, Sequence, Set
from fractions import Fraction
from typing import Optional, Union

from cdd import LPObjType, LPSolverType, LPStatusType, RepType
from cdd import LPObjType, LPSolverType, LPStatusType, RepType, RowOrderType

NumberType = Fraction
SupportsNumberType = Union[Fraction, int]
Expand Down Expand Up @@ -76,4 +76,6 @@ def matrix_from_array(
obj_type: LPObjType = LPObjType.NONE,
obj_func: Optional[Sequence[SupportsNumberType]] = None,
) -> Matrix: ...
def polyhedron_from_matrix(mat: Matrix) -> Polyhedron: ...
def polyhedron_from_matrix(
mat: Matrix, row_order_type: Optional[RowOrderType] = None
) -> Polyhedron: ...
28 changes: 28 additions & 0 deletions test/test_polyhedron.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from collections.abc import Sequence, Set
from fractions import Fraction
from typing import Optional

import pytest

import cdd

Expand Down Expand Up @@ -78,3 +81,28 @@ def test_polyhedron_cube_2() -> None:
poly = cdd.polyhedron_from_matrix(mat)
assert_matrix_almost_equal(cdd.copy_generators(poly).array, generators)
assert_matrix_almost_equal(cdd.copy_inequalities(poly).array, inequalities)


@pytest.mark.parametrize(
"row_order_type,order",
[
(cdd.RowOrderType.MAX_INDEX, [2, 3, 0, 1]),
(cdd.RowOrderType.MIN_INDEX, [2, 1, 0, 3]),
(cdd.RowOrderType.MIN_CUTOFF, [1, 0, 2, 3]),
(cdd.RowOrderType.MAX_CUTOFF, [1, 0, 2, 3]),
(cdd.RowOrderType.MIX_CUTOFF, [1, 0, 2, 3]),
(cdd.RowOrderType.LEX_MIN, [0, 1, 2, 3]),
(cdd.RowOrderType.LEX_MAX, [2, 3, 0, 1]),
],
)
def test_polyhedron_row_order_type(
row_order_type: Optional[cdd.RowOrderType], order: Sequence[int]
) -> None:
generators = [[1, 1, 0], [1, 0, 0], [1, 0, 1], [1, 1, 1]]
inequalities = [[0, 0, 1], [0, 1, 0], [1, 0, -1], [1, -1, 0]]
mat = cdd.matrix_from_array(inequalities, rep_type=cdd.RepType.INEQUALITY)
poly = cdd.polyhedron_from_matrix(mat, row_order_type=row_order_type)
print(cdd.copy_generators(poly).array)
assert_matrix_almost_equal(
cdd.copy_generators(poly).array, [generators[i] for i in order]
)

0 comments on commit 219b845

Please sign in to comment.