diff --git a/cython/_cdd.pyx b/cython/_cdd.pyx index f8bf695..fd696bd 100644 --- a/cython/_cdd.pyx +++ b/cython/_cdd.pyx @@ -19,6 +19,11 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +from typing import SupportsFloat + +NumberType = float +SupportsNumberType = SupportsFloat + cdef extern from * nogil: "#undef GMPRATIONAL" diff --git a/cython/_cddgmp.pyx b/cython/_cddgmp.pyx index b5e76f5..e5bdf81 100644 --- a/cython/_cddgmp.pyx +++ b/cython/_cddgmp.pyx @@ -19,6 +19,14 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +from fractions import Fraction +from typing import Union + +from cdd import LPObjType, LPSolverType, LPStatusType, RepType + +NumberType = Fraction +SupportsNumberType = Union[Fraction, int] + cdef extern from * nogil: "#define GMPRATIONAL" @@ -27,9 +35,6 @@ include "setoper.pxi" include "mytype_gmp.pxi" include "cdd.pxi" -from cdd import LPObjType, LPSolverType, LPStatusType, RepType - - cdef dd_NumberType NUMBER_TYPE = dd_Rational include "pycddlib.pxi" diff --git a/cython/pycddlib.pxi b/cython/pycddlib.pxi index 44e2081..2e519ca 100644 --- a/cython/pycddlib.pxi +++ b/cython/pycddlib.pxi @@ -122,15 +122,8 @@ cdef class Matrix: property array: def __get__(self): - cdef dd_rowrange i - cdef dd_colrange j - return [ - [ - _get_mytype(self.dd_mat.matrix[i][j]) - for j in range(self.dd_mat.colsize) - ] - for i in range(self.dd_mat.rowsize) - ] + cdef _Shape shape = _Shape(self.dd_mat.rowsize, self.dd_mat.colsize) + return _get_array_from_matrix(self.dd_mat.matrix, shape) property lin_set: def __get__(self): @@ -213,7 +206,7 @@ cdef _array_shape(array): raise ValueError("array too large") return shape -cdef _set_matrix(mytype **pp, _Shape shape, array): +cdef _set_matrix_from_array(mytype **pp, _Shape shape, array): for rowindex, row in enumerate(array): if len(row) != shape.numcols: raise ValueError("rows have different lengths") @@ -221,6 +214,15 @@ cdef _set_matrix(mytype **pp, _Shape shape, array): _set_mytype(pp[rowindex][colindex], value) +cdef _get_array_from_matrix(mytype **pp, _Shape shape): + cdef dd_rowrange i + cdef dd_colrange j + return [ + [_get_mytype(pp[i][j]) for j in range(shape.numcols)] + for i in range(shape.numrows) + ] + + # create matrix and wrap into Matrix class # https://cython.readthedocs.io/en/latest/src/userguide/extension_types.html#instantiation-from-existing-c-c-pointers def matrix_from_array( @@ -237,7 +239,7 @@ def matrix_from_array( if dd_mat == NULL: raise MemoryError try: - _set_matrix(dd_mat.matrix, shape, array) + _set_matrix_from_array(dd_mat.matrix, shape, array) _set_set(dd_mat.linset, lin_set) dd_mat.representation = rep_type dd_mat.objective = obj_type @@ -287,15 +289,8 @@ cdef class LinProg: property array: def __get__(self): - cdef dd_rowrange i - cdef dd_colrange j - return [ - [ - _get_mytype(self.dd_lp.A[i][j]) - for j in range(self.dd_lp.d) - ] - for i in range(self.dd_lp.m) - ] + cdef _Shape shape = _Shape(self.dd_lp.m, self.dd_lp.d) + return _get_array_from_matrix(self.dd_lp.A, shape) property obj_type: def __get__(self): @@ -383,7 +378,7 @@ def linprog_from_array(array, dd_LPObjectiveType obj_type): if dd_lp == NULL: raise MemoryError try: - _set_matrix(dd_lp.A, shape, array) + _set_matrix_from_array(dd_lp.A, shape, array) except: # noqa: E722 dd_FreeLPData(dd_lp) raise @@ -398,48 +393,79 @@ def linprog_solve(LinProg linprog, dd_LPSolverType solver=dd_DualSimplex): cdef class Polyhedron: - cdef dd_PolyhedraPtr dd_poly + property rep_type: + def __get__(self): + return RepType(self.dd_poly.representation) + def __str__(self): cdef libc.stdio.FILE *pfile pfile = _tmpfile() dd_WritePolyFile(pfile, self.dd_poly) return _tmpread(pfile).rstrip('\n') - def __cinit__(self, Matrix mat): - cdef dd_ErrorType error = dd_NoError - # initialize pointers - self.dd_poly = NULL - # read matrix - self.dd_poly = dd_DDMatrix2Poly(mat.dd_mat, &error) - if self.dd_poly == NULL or error != dd_NoError: - # do not call dd_FreePolyhedra(self.dd_poly) - # see issue #7 - _raise_error(error, "failed to load polyhedra") + def __init__(self): + raise TypeError("This class cannot be instantiated directly.") def __dealloc__(self): if self.dd_poly: dd_FreePolyhedra(self.dd_poly) self.dd_poly = NULL - def get_inequalities(self): - return matrix_from_ptr(dd_CopyInequalities(self.dd_poly)) +cdef polyhedron_from_ptr(dd_PolyhedraPtr dd_poly): + if dd_poly == NULL: + raise MemoryError # assume malloc failed + cdef Polyhedron poly = Polyhedron.__new__(Polyhedron) + poly.dd_poly = dd_poly + return poly + + +def polyhedron_from_matrix(Matrix mat): + if mat.rep_type != dd_Inequality and mat.rep_type != 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 dd_poly == NULL: + raise MemoryError + if error != dd_NoError: + # TODO should call dd_FreePolyhedra(dd_poly)... see issue #7 + _raise_error(error, "failed to load polyhedra") + return polyhedron_from_ptr(dd_poly) + + +def copy_input(Polyhedron poly): + return matrix_from_ptr(dd_CopyInput(poly.dd_poly)) + + +def copy_output(Polyhedron poly): + return matrix_from_ptr(dd_CopyOutput(poly.dd_poly)) + + + +def copy_inequalities(Polyhedron poly): + return matrix_from_ptr(dd_CopyInequalities(poly.dd_poly)) + + +def copy_generators(Polyhedron poly): + return matrix_from_ptr(dd_CopyGenerators(poly.dd_poly)) + + +def copy_adjacency(Polyhedron poly): + return _get_dd_setfam(dd_CopyAdjacency(poly.dd_poly)) + + +def copy_input_adjacency(Polyhedron poly): + return _get_dd_setfam(dd_CopyInputAdjacency(poly.dd_poly)) - def get_generators(self): - return matrix_from_ptr(dd_CopyGenerators(self.dd_poly)) - def get_adjacency(self): - return _get_dd_setfam(dd_CopyAdjacency(self.dd_poly)) +def copy_incidence(Polyhedron poly): + return _get_dd_setfam(dd_CopyIncidence(poly.dd_poly)) - def get_input_adjacency(self): - return _get_dd_setfam(dd_CopyInputAdjacency(self.dd_poly)) - def get_incidence(self): - return _get_dd_setfam(dd_CopyIncidence(self.dd_poly)) +def copy_input_incidence(Polyhedron poly): + return _get_dd_setfam(dd_CopyInputIncidence(poly.dd_poly)) - def get_input_incidence(self): - return _get_dd_setfam(dd_CopyInputIncidence(self.dd_poly)) # module initialization code comes here # initialize module constants diff --git a/docs/source/polyhedron.rst b/docs/source/polyhedron.rst index cfe2ae0..6c528ff 100644 --- a/docs/source/polyhedron.rst +++ b/docs/source/polyhedron.rst @@ -96,7 +96,7 @@ This is the sampleh1.ine example that comes with cddlib. >>> mat = cdd.matrix_from_array([[2,-1,-1,0],[0,1,0,0],[0,0,1,0]]) >>> mat.rep_type = cdd.RepType.INEQUALITY ->>> poly = cdd.Polyhedron(mat) +>>> poly = cdd.polyhedron_from_matrix(mat) >>> print(poly) # doctest: +NORMALIZE_WHITESPACE begin 3 4 real @@ -104,7 +104,7 @@ begin 0 1 0 0 0 0 1 0 end ->>> ext = poly.get_generators() +>>> ext = cdd.copy_generators(poly) >>> print(ext) # doctest: +NORMALIZE_WHITESPACE V-representation linearity 1 4 @@ -128,9 +128,9 @@ The following example illustrates how to get adjacencies and incidences. >>> # 0 <= 1 - x2 (face 3) >>> mat = cdd.matrix_from_array([[1, 1, 0], [1, 0, 1], [1, -1, 0], [1, 0, -1]]) >>> mat.rep_type = cdd.RepType.INEQUALITY ->>> poly = cdd.Polyhedron(mat) +>>> poly = cdd.polyhedron_from_matrix(mat) >>> # The V-representation can be printed in the usual way: ->>> gen = poly.get_generators() +>>> gen = cdd.copy_generators(poly) >>> print(gen) # doctest: +NORMALIZE_WHITESPACE V-representation begin @@ -154,30 +154,30 @@ end >>> # vertex 1 is adjacent to vertices 0 and 2 >>> # vertex 2 is adjacent to vertices 1 and 3 >>> # vertex 3 is adjacent to vertices 0 and 2 ->>> print([list(x) for x in poly.get_adjacency()]) +>>> print([list(x) for x in cdd.copy_adjacency(poly)]) [[1, 3], [0, 2], [1, 3], [0, 2]] >>> # vertex 0 is the intersection of faces (1) and (2) >>> # vertex 1 is the intersection of faces (2) and (3) >>> # vertex 2 is the intersection of faces (0) and (3) >>> # vertex 3 is the intersection of faces (0) and (1) ->>> print([list(x) for x in poly.get_incidence()]) +>>> print([list(x) for x in cdd.copy_incidence(poly)]) [[1, 2], [2, 3], [0, 3], [0, 1]] >>> # face (0) is adjacent to faces (1) and (3) >>> # face (1) is adjacent to faces (0) and (2) >>> # face (2) is adjacent to faces (1) and (3) >>> # face (3) is adjacent to faces (0) and (2) ->>> print([list(x) for x in poly.get_input_adjacency()]) +>>> print([list(x) for x in cdd.copy_input_adjacency(poly)]) [[1, 3], [0, 2], [1, 3], [0, 2], []] >>> # face (0) intersects with vertices 2 and 3 >>> # face (1) intersects with vertices 0 and 3 >>> # face (2) intersects with vertices 0 and 1 >>> # face (3) intersects with vertices 1 and 2 ->>> print([list(x) for x in poly.get_input_incidence()]) +>>> print([list(x) for x in cdd.copy_input_incidence(poly)]) [[2, 3], [0, 3], [0, 1], [1, 2], []] >>> # add a vertex, and construct new polyhedron >>> cdd.matrix_append_to(gen, cdd.matrix_from_array([[1, 0, 2]])) >>> vpoly = cdd.Polyhedron(gen) ->>> print(vpoly.get_inequalities()) # doctest: +NORMALIZE_WHITESPACE +>>> print(cdd.copy_inequalities(vpoly)) # doctest: +NORMALIZE_WHITESPACE H-representation begin 5 3 real @@ -210,14 +210,14 @@ end >>> # 3---(0)---0 >>> # >>> # for each face, list adjacent faces ->>> print([list(x) for x in vpoly.get_adjacency()]) +>>> print([list(x) for x in cdd.copy_adjacency(vpoly)]) [[2, 4], [2, 3], [0, 1], [1, 4], [0, 3]] >>> # for each face, list adjacent vertices ->>> print([list(x) for x in vpoly.get_incidence()]) +>>> print([list(x) for x in cdd.copy_incidence(vpoly)]) [[0, 3], [2, 4], [2, 3], [1, 4], [0, 1]] >>> # for each vertex, list adjacent vertices ->>> print([list(x) for x in vpoly.get_input_adjacency()]) +>>> print([list(x) for x in cdd.copy_input_adjacency(vpoly)]) [[1, 3], [0, 4], [3, 4], [0, 2], [1, 2]] >>> # for each vertex, list adjacent faces ->>> print([list(x) for x in vpoly.get_input_incidence()]) +>>> print([list(x) for x in cdd.copy_input_incidence(vpoly)]) [[0, 4], [3, 4], [1, 2], [0, 2], [1, 3]] diff --git a/src/cdd/__init__.pyi b/src/cdd/__init__.pyi index dd62574..62a0f3b 100644 --- a/src/cdd/__init__.pyi +++ b/src/cdd/__init__.pyi @@ -1,4 +1,4 @@ -from collections.abc import Container, Iterable, Sequence, Set +from collections.abc import Container, Sequence, Set from enum import IntFlag from typing import ClassVar, Optional, SupportsFloat @@ -26,17 +26,20 @@ class RepType(IntFlag): INEQUALITY: ClassVar[RepType] = ... UNSPECIFIED: ClassVar[RepType] = ... +NumberType = float +SupportsNumberType = SupportsFloat + class Matrix: @property - def array(self) -> Sequence[Sequence[float]]: ... + def array(self) -> Sequence[Sequence[NumberType]]: ... @property def lin_set(self) -> Set[int]: ... @lin_set.setter def lin_set(self, value: Container[int]) -> None: ... @property - def obj_func(self) -> Sequence[float]: ... + def obj_func(self) -> Sequence[NumberType]: ... @obj_func.setter - def obj_func(self, value: Sequence[float]) -> None: ... + def obj_func(self, value: Sequence[NumberType]) -> None: ... @property def obj_type(self) -> LPObjType: ... @obj_type.setter @@ -47,49 +50,52 @@ class Matrix: def rep_type(self, value: RepType) -> None: ... def matrix_from_array( - array: Sequence[Sequence[SupportsFloat]], + array: Sequence[Sequence[SupportsNumberType]], lin_set: Container[int] = (), rep_type: RepType = RepType.UNSPECIFIED, obj_type: LPObjType = LPObjType.NONE, - obj_func: Optional[Sequence[SupportsFloat]] = None, + obj_func: Optional[Sequence[SupportsNumberType]] = None, ) -> Matrix: ... -def matrix_append_to(matrix1: Matrix, matrix2: Matrix) -> None: ... -def matrix_canonicalize(matrix: Matrix) -> None: ... -def matrix_copy(matrix: Matrix) -> Matrix: ... +def matrix_append_to(mat1: Matrix, mat2: Matrix) -> None: ... +def matrix_canonicalize(mat: Matrix) -> None: ... +def matrix_copy(mat: Matrix) -> Matrix: ... class LinProg: @property - def array(self) -> Sequence[Sequence[float]]: ... + def array(self) -> Sequence[Sequence[NumberType]]: ... @property def obj_type(self) -> LPObjType: ... @obj_type.setter def obj_type(self, value: LPObjType) -> None: ... @property - def dual_solution(self) -> Sequence[tuple[int, float]]: ... + def dual_solution(self) -> Sequence[tuple[int, NumberType]]: ... @property - def obj_value(self) -> float: ... + def obj_value(self) -> NumberType: ... @property - def primal_solution(self) -> Sequence[float]: ... + def primal_solution(self) -> Sequence[NumberType]: ... @property def status(self) -> LPStatusType: ... @property def solver(self) -> LPSolverType: ... -def linprog_from_matrix(matrix: Matrix) -> LinProg: ... +def linprog_from_matrix(mat: Matrix) -> LinProg: ... def linprog_from_array( - array: Sequence[Sequence[float]], obj_type: LPObjType + array: Sequence[Sequence[NumberType]], obj_type: LPObjType ) -> LinProg: ... def linprog_solve( - linprog: LinProg, solver: LPSolverType = LPSolverType.DUAL_SIMPLEX + lp: LinProg, solver: LPSolverType = LPSolverType.DUAL_SIMPLEX ) -> None: ... class Polyhedron: @property def rep_type(self) -> RepType: ... - def __init__(self, mat: Matrix) -> None: ... - def get_generators(self) -> Matrix: ... - def get_inequalities(self) -> Matrix: ... - def get_adjacency(self) -> Sequence[Set[int]]: ... - def get_incidence(self) -> Sequence[Set[int]]: ... - def get_input_adjacency(self) -> Sequence[Set[int]]: ... - def get_input_incidence(self) -> Sequence[Set[int]]: ... + +def polyhedron_from_matrix(mat: Matrix) -> Polyhedron: ... +def copy_input(poly: Polyhedron) -> Matrix: ... +def copy_output(poly: Polyhedron) -> Matrix: ... +def copy_generators(poly: Polyhedron) -> Matrix: ... +def copy_inequalities(poly: Polyhedron) -> Matrix: ... +def copy_adjacency(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_incidence(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_input_adjacency(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_input_incidence(poly: Polyhedron) -> Sequence[Set[int]]: ... diff --git a/src/cdd/gmp.pyi b/src/cdd/gmp.pyi index b470a08..ce33cd6 100644 --- a/src/cdd/gmp.pyi +++ b/src/cdd/gmp.pyi @@ -1,20 +1,23 @@ -from collections.abc import Container, Iterable, Sequence, Set +from collections.abc import Container, Sequence, Set from fractions import Fraction from typing import Optional, Union from cdd import LPObjType, LPSolverType, LPStatusType, RepType +NumberType = Fraction +SupportsNumberType = Union[Fraction, int] + class Matrix: @property - def array(self) -> Sequence[Sequence[Fraction]]: ... + def array(self) -> Sequence[Sequence[NumberType]]: ... @property def lin_set(self) -> Set[int]: ... @lin_set.setter def lin_set(self, value: Container[int]) -> None: ... @property - def obj_func(self) -> Sequence[Fraction]: ... + def obj_func(self) -> Sequence[NumberType]: ... @obj_func.setter - def obj_func(self, value: Sequence[Fraction]) -> None: ... + def obj_func(self, value: Sequence[NumberType]) -> None: ... @property def obj_type(self) -> LPObjType: ... @obj_type.setter @@ -25,49 +28,52 @@ class Matrix: def rep_type(self, value: RepType) -> None: ... def matrix_from_array( - array: Sequence[Sequence[Union[Fraction, int]]], + array: Sequence[Sequence[SupportsNumberType]], lin_set: Container[int] = (), rep_type: RepType = RepType.UNSPECIFIED, obj_type: LPObjType = LPObjType.NONE, - obj_func: Optional[Sequence[Union[Fraction, int]]] = None, + obj_func: Optional[Sequence[SupportsNumberType]] = None, ) -> Matrix: ... -def matrix_append_to(matrix1: Matrix, matrix2: Matrix) -> None: ... -def matrix_canonicalize(matrix: Matrix) -> None: ... -def matrix_copy(matrix: Matrix) -> Matrix: ... +def matrix_append_to(mat1: Matrix, mat2: Matrix) -> None: ... +def matrix_canonicalize(mat: Matrix) -> None: ... +def matrix_copy(mat: Matrix) -> Matrix: ... class LinProg: @property - def array(self) -> Sequence[Sequence[Fraction]]: ... + def array(self) -> Sequence[Sequence[NumberType]]: ... @property def obj_type(self) -> LPObjType: ... @obj_type.setter def obj_type(self, value: LPObjType) -> None: ... @property - def dual_solution(self) -> Sequence[tuple[int, Fraction]]: ... + def dual_solution(self) -> Sequence[tuple[int, NumberType]]: ... @property - def obj_value(self) -> Fraction: ... + def obj_value(self) -> NumberType: ... @property - def primal_solution(self) -> Sequence[Fraction]: ... + def primal_solution(self) -> Sequence[NumberType]: ... @property def status(self) -> LPStatusType: ... @property def solver(self) -> LPSolverType: ... -def linprog_from_matrix(matrix: Matrix) -> LinProg: ... +def linprog_from_matrix(mat: Matrix) -> LinProg: ... def linprog_from_array( - array: Sequence[Sequence[float]], obj_type: LPObjType + array: Sequence[Sequence[NumberType]], obj_type: LPObjType ) -> LinProg: ... def linprog_solve( - linprog: LinProg, solver: LPSolverType = LPSolverType.DUAL_SIMPLEX + lp: LinProg, solver: LPSolverType = LPSolverType.DUAL_SIMPLEX ) -> None: ... class Polyhedron: @property def rep_type(self) -> RepType: ... - def __init__(self, mat: Matrix) -> None: ... - def get_generators(self) -> Matrix: ... - def get_inequalities(self) -> Matrix: ... - def get_adjacency(self) -> Sequence[Set[int]]: ... - def get_incidence(self) -> Sequence[Set[int]]: ... - def get_input_adjacency(self) -> Sequence[Set[int]]: ... - def get_input_incidence(self) -> Sequence[Set[int]]: ... + +def polyhedron_from_matrix(mat: Matrix) -> Polyhedron: ... +def copy_input(poly: Polyhedron) -> Matrix: ... +def copy_output(poly: Polyhedron) -> Matrix: ... +def copy_generators(poly: Polyhedron) -> Matrix: ... +def copy_inequalities(poly: Polyhedron) -> Matrix: ... +def copy_adjacency(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_incidence(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_input_adjacency(poly: Polyhedron) -> Sequence[Set[int]]: ... +def copy_input_incidence(poly: Polyhedron) -> Sequence[Set[int]]: ... diff --git a/test/test_adjacency_list.py b/test/test_adjacency_list.py index c849589..bde720d 100644 --- a/test/test_adjacency_list.py +++ b/test/test_adjacency_list.py @@ -2,7 +2,7 @@ def test_make_vertex_adjacency_list() -> None: - # The following lines test that poly.get_adjacency_list() + # The following lines test that cdd.copy_adjacency_list(poly) # returns the correct adjacencies. # We start with the H-representation for a cube @@ -17,8 +17,10 @@ def test_make_vertex_adjacency_list() -> None: ], rep_type=cdd.RepType.INEQUALITY, ) - poly = cdd.Polyhedron(mat) - adjacency = poly.get_adjacency() + assert mat.rep_type == cdd.RepType.INEQUALITY + poly = cdd.polyhedron_from_matrix(mat) + assert poly.rep_type == cdd.RepType.INEQUALITY + adjacency = cdd.copy_adjacency(poly) # Family size should equal the number of vertices of the cube (8) assert len(adjacency) == 8 @@ -55,7 +57,7 @@ def test_make_facet_adjacency_list() -> None: ], rep_type=cdd.RepType.INEQUALITY, ) - poly = cdd.Polyhedron(mat) + poly = cdd.polyhedron_from_matrix(mat) adjacency_list = [ [1, 2, 3, 4, 6], @@ -67,5 +69,5 @@ def test_make_facet_adjacency_list() -> None: [0, 3, 4, 5], ] - adjacency = poly.get_input_adjacency() + adjacency = cdd.copy_input_adjacency(poly) assert adjacency == [frozenset(x) for x in adjacency_list] diff --git a/test/test_incidence.py b/test/test_incidence.py index 265c8a3..35959e5 100644 --- a/test/test_incidence.py +++ b/test/test_incidence.py @@ -2,7 +2,7 @@ def test_vertex_incidence_cube() -> None: - # The following lines test that poly.get_vertex_incidence() + # The following lines test that cdd.copy_vertex_incidence(poly) # returns the correct incidences. # We start with the H-representation for a cube @@ -17,8 +17,8 @@ def test_vertex_incidence_cube() -> None: ] ) mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) - incidence = poly.get_incidence() + poly = cdd.polyhedron_from_matrix(mat) + incidence = cdd.copy_incidence(poly) # Family size should equal the number of vertices of the cube (8) assert len(incidence) == 8 @@ -56,7 +56,7 @@ def test_vertex_incidence_vtest_vo() -> None: ) mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) + poly = cdd.polyhedron_from_matrix(mat) incidence_list = [ {0, 4, 6}, @@ -71,7 +71,7 @@ def test_vertex_incidence_vtest_vo() -> None: {2, 4, 5}, ] - incidence = poly.get_incidence() + incidence = cdd.copy_incidence(poly) assert incidence == [frozenset(x) for x in incidence_list] @@ -88,8 +88,8 @@ def test_facet_incidence_cube() -> None: ] ) mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) - incidence = poly.get_input_incidence() + poly = cdd.polyhedron_from_matrix(mat) + incidence = cdd.copy_input_incidence(poly) # Family size should equal the number of facets of the cube (6), # plus 1 (the empty infinite ray) @@ -128,7 +128,7 @@ def test_facet_incidence_vtest_vo() -> None: ) mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) + poly = cdd.polyhedron_from_matrix(mat) incidence_list = [ {0, 1, 2, 3, 4}, @@ -140,4 +140,4 @@ def test_facet_incidence_vtest_vo() -> None: {0, 4, 7, 8}, ] - assert poly.get_input_incidence() == [frozenset(x) for x in incidence_list] + assert cdd.copy_input_incidence(poly) == [frozenset(x) for x in incidence_list] diff --git a/test/test_issue20.py b/test/test_issue20.py index 9b7b2ad..9e8e4df 100644 --- a/test/test_issue20.py +++ b/test/test_issue20.py @@ -13,6 +13,6 @@ def test_issue20() -> None: ) mat = cdd.matrix_from_array(arr) # type: ignore mat.rep_type = cdd.RepType.GENERATOR - cdd_poly = cdd.Polyhedron(mat) - ineq = np.array(cdd_poly.get_inequalities().array) + cdd_poly = cdd.polyhedron_from_matrix(mat) + ineq = np.array(cdd.copy_inequalities(cdd_poly).array) assert ((ref_ineq - ineq) == 0).all() diff --git a/test/test_issue25.py b/test/test_issue25.py index 9384ead..a6ba1ef 100644 --- a/test/test_issue25.py +++ b/test/test_issue25.py @@ -3,5 +3,5 @@ # check that empty polyhedron does not cause segfault def test_issue25() -> None: - mat = cdd.matrix_from_array([]) - cdd.Polyhedron(mat) + mat = cdd.matrix_from_array([], rep_type=cdd.RepType.INEQUALITY) + cdd.polyhedron_from_matrix(mat) diff --git a/test/test_issue7.py b/test/test_issue7.py index cb591ad..a5c9ea3 100644 --- a/test/test_issue7.py +++ b/test/test_issue7.py @@ -5,7 +5,7 @@ # Check that numerical inconsistency is reported properly. def test_issue7() -> None: - m = [ + array = [ [1.0, -4.0, -40.0, -4.0, 30.0677432, -0.93140119, -20.75373128], [1.0, 4.0, -40.0, -4.0, 31.02398625, 5.00096, -18.98561378], [1.0, -4.0, -40.0, -4.0, 31.02398625, -1.09504, -20.07358622], @@ -17,7 +17,6 @@ def test_issue7() -> None: [1.0, -4.0, 40.0, 4.0, -31.21985375, -4.91296, 17.90974622], [1.0, 4.0, 40.0, -4.0, -28.86014625, 4.91296, 20.26945371], ] - m2 = cdd.matrix_from_array(m) - m2.rep_type = cdd.RepType.GENERATOR + mat = cdd.matrix_from_array(array, rep_type=cdd.RepType.GENERATOR) with pytest.raises(RuntimeError, match="inconsistency"): - cdd.Polyhedron(m2) + cdd.polyhedron_from_matrix(mat) diff --git a/test/test_polyhedron.py b/test/test_polyhedron.py index d158f6e..820057a 100644 --- a/test/test_polyhedron.py +++ b/test/test_polyhedron.py @@ -9,14 +9,14 @@ def test_polyhedron_type() -> None: mat = cdd.matrix_from_array([[1, 1], [1, -1]]) mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) - assert isinstance(poly.get_generators(), cdd.Matrix) - assert isinstance(poly.get_inequalities(), cdd.Matrix) + poly = cdd.polyhedron_from_matrix(mat) + assert isinstance(cdd.copy_generators(poly), cdd.Matrix) + assert isinstance(cdd.copy_inequalities(poly), cdd.Matrix) for xss in [ - poly.get_adjacency(), - poly.get_input_adjacency(), - poly.get_incidence(), - poly.get_input_incidence(), + cdd.copy_adjacency(poly), + cdd.copy_input_adjacency(poly), + cdd.copy_incidence(poly), + cdd.copy_input_incidence(poly), ]: assert isinstance(xss, Sequence) for xs in xss: @@ -26,25 +26,22 @@ def test_polyhedron_type() -> None: def test_sampleh1() -> None: - mat = cdd.matrix_from_array([[2, -1, -1, 0], [0, 1, 0, 0], [0, 0, 1, 0]]) - mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) - ext = poly.get_generators() + array = [[2, -1, -1, 0], [0, 1, 0, 0], [0, 0, 1, 0]] + mat = cdd.matrix_from_array(array, rep_type=cdd.RepType.INEQUALITY) + poly = cdd.polyhedron_from_matrix(mat) + ext = cdd.copy_generators(poly) assert ext.rep_type == cdd.RepType.GENERATOR assert_matrix_almost_equal( ext.array, [[1, 0, 0, 0], [1, 2, 0, 0], [1, 0, 2, 0], [0, 0, 0, 1]] ) - # note: first row is 0, so fourth row is 3 - assert ext.lin_set == {3} + assert ext.lin_set == {3} # first row is 0, so fourth row is 3 def test_testcdd2() -> None: - mat = cdd.matrix_from_array([[7, -3, -0], [7, 0, -3], [1, 1, 0], [1, 0, 1]]) - mat.rep_type = cdd.RepType.INEQUALITY - assert_matrix_almost_equal( - mat.array, [(7, -3, -0), (7, 0, -3), (1, 1, 0), (1, 0, 1)] - ) - gen = cdd.Polyhedron(mat).get_generators() + array = [[7, -3, -0], [7, 0, -3], [1, 1, 0], [1, 0, 1]] + mat = cdd.matrix_from_array(array, rep_type=cdd.RepType.INEQUALITY) + assert_matrix_almost_equal(mat.array, array) + gen = cdd.copy_generators(cdd.polyhedron_from_matrix(mat)) assert gen.rep_type == cdd.RepType.GENERATOR assert_matrix_almost_equal( gen.array, @@ -58,12 +55,9 @@ def test_testcdd2() -> None: # add an equality and an inequality cdd.matrix_append_to(mat, cdd.matrix_from_array([[7, 1, -3]], lin_set={0})) cdd.matrix_append_to(mat, cdd.matrix_from_array([[7, -3, 1]])) - assert_matrix_almost_equal( - mat.array, - [(7, -3, -0), (7, 0, -3), (1, 1, 0), (1, 0, 1), (7, 1, -3), (7, -3, 1)], - ) + assert_matrix_almost_equal(mat.array, array + [[7, 1, -3], [7, -3, 1]]) assert mat.lin_set == {4} - gen2 = cdd.Polyhedron(mat).get_generators() + gen2 = cdd.copy_generators(cdd.polyhedron_from_matrix(mat)) assert gen2.rep_type == cdd.RepType.GENERATOR assert_matrix_almost_equal(gen2.array, [(1, -1, 2), (1, 0, Fraction(7, 3))]) @@ -71,18 +65,16 @@ def test_testcdd2() -> None: def test_polyhedron_cube_1() -> None: generators = [[1, 0, 1], [1, 1, 0], [1, 1, 1], [1, 0, 0]] inequalities = [[0, 0, 1], [0, 1, 0], [1, 0, -1], [1, -1, 0]] - mat = cdd.matrix_from_array(generators) - mat.rep_type = cdd.RepType.GENERATOR - poly = cdd.Polyhedron(mat) - assert_matrix_almost_equal(poly.get_generators().array, generators) - assert_matrix_almost_equal(poly.get_inequalities().array, inequalities) + mat = cdd.matrix_from_array(generators, rep_type=cdd.RepType.GENERATOR) + 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) def test_polyhedron_cube_2() -> None: generators = [[1, 1, 0], [1, 0, 0], [1, 0, 1], [1, 1, 1]] # same up to ordering inequalities = [[0, 0, 1], [0, 1, 0], [1, 0, -1], [1, -1, 0]] - mat = cdd.matrix_from_array(inequalities) - mat.rep_type = cdd.RepType.INEQUALITY - poly = cdd.Polyhedron(mat) - assert_matrix_almost_equal(poly.get_generators().array, generators) - assert_matrix_almost_equal(poly.get_inequalities().array, inequalities) + mat = cdd.matrix_from_array(inequalities, rep_type=cdd.RepType.INEQUALITY) + 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)