Skip to content

Commit 1fe7740

Browse files
committed
add additional methods to NNC_polyhedron class
1 parent 3e9e2bb commit 1fe7740

6 files changed

Lines changed: 86 additions & 67 deletions

File tree

pplite/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Acadia Larsen (2024): initial version.
1111
"""
1212

13-
__version__ = "0.0.53"
13+
__version__ = "0.0.54"
1414

1515
from .linear_algebra import (
1616
Variable, Linear_Expression, Affine_Expression

pplite/constraint.pyx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ cdef class Constraint(object):
172172
INPUT: None
173173
OUPUT: A tuple of coefficients
174174
"""
175-
175+
raise NotImplementedError
176176

177177
def linear_form(self):
178178
"""
@@ -587,10 +587,10 @@ cdef _make_Constraint_from_richcmp(lhs_, rhs_, op):
587587
raise NotImplementedError
588588
else:
589589
assert(False)
590-
if isinstance(lhs_, Variable): # variable not explitly declared. promote var to linear expression and compare.
590+
if isinstance(lhs_, Variable): # Variable not explicitly declared. Promote var to linear expression and compare.
591591
lhs_ = Linear_Expression(lhs_)
592592
return _make_Constraint_from_richcmp(lhs_, rhs_, op)
593-
if isinstance(rhs_, Variable): # variable not explitly declared. promote var to linear expression and compare.
593+
if isinstance(rhs_, Variable): # Variable not explicitly declared. Promote var to linear expression and compare.
594594
rhs_ = Linear_Expression(rhs_)
595595
return _make_Constraint_from_richcmp(lhs_, rhs_, op)
596596

@@ -605,7 +605,6 @@ cdef _wrap_Constraint(Con constraint):
605605

606606

607607
# Reproduction of these functions here is necessary. Removing this causes things to break.
608-
# Investigation is pending.
609608
cdef FLINT_Integer_to_Python(FLINT_Integer& integer):
610609
r""" Converts FLINT_Integer to python integer."""
611610
cdef mpz_t new_int
@@ -631,7 +630,7 @@ cdef FLINT_Integer Python_int_to_FLINT_Integer(integer):
631630

632631
def FLINT_Integer_Conversion_Check(possible_integer):
633632
"""
634-
Checks a python object is convertable to a FLINT_Integer.
633+
Checks a python object is convertible to a FLINT_Integer.
635634
636635
Input: Object
637636

pplite/generators.pyx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,6 @@ def Ray(linear_expression):
460460
### Helper Functions ###
461461
########################
462462

463-
# TODO migrate helper functions to a single module.
464-
465463
cdef GenType string_to_GenType(t):
466464
"""
467465
Converts a string to an enum pplite::GenType.

pplite/linear_algebra.pyx

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ cdef FLINT_Integer Python_int_to_FLINT_Integer(integer):
2929
fmpz_init(x)
3030
fmpz_set_si(x, integer)
3131
return FLINT_Integer(x)
32-
if MPZ_Check(integer): # is this okay?
32+
if MPZ_Check(integer): # This is a little hacky...
3333
y = <fmpz> integer
3434
return FLINT_Integer(y)
3535
raise ValueError("Integer Conversion Failed")
@@ -453,11 +453,9 @@ cdef class Linear_Expression(object):
453453
mpz(1)
454454
>>> expr.coefficient(Variable(124))
455455
mpz(0)
456-
457-
String, rationals and floating point types are accepted as long as they
458-
represent exact integers:
459456
"""
460-
# TODO: Finish Tests/claim above.
457+
# TODO: Check that string, rationals and floating point types are accepted as long as they
458+
# represent exact integers.
461459
def __init__(self, *args):
462460
"""
463461
The Cython constructor.

pplite/polyhedron.pyx

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ cdef class NNC_Polyhedron(object):
276276
raise TypeError("other_poly needs to be of :class:`NNC_Polyhedron`")
277277

278278
def get_bounding_box(self):
279-
pass
279+
raise NotImplementedError
280280

281281
def boxed_contains(self, other_poly):
282282
cdef Poly* yy
@@ -372,7 +372,7 @@ cdef class NNC_Polyhedron(object):
372372
return i
373373

374374
def _get_boundes_itv(self, itv_expr):
375-
pass
375+
raise NotImplementedError
376376

377377
def get_bounds(self, variable_or_affine_expr):
378378
if isinstance(variable_or_affine_expr, Variable):
@@ -382,27 +382,31 @@ cdef class NNC_Polyhedron(object):
382382
raise TypeError("A :class:`Variable` or a :class:`Affine_Expression` should be passed into this method.")
383383

384384
def get_unconstrainted(self):
385-
pass
385+
raise NotImplementedError
386386

387+
388+
# For both the constraints and generators methods should be implemented via cons_sys and gens_sys.
389+
# At the moment, we use the copy constructor because it was easier to write.
387390
def constraints(self):
388-
# Access constraints indirectly via copy_cons()
389-
# TODO: Properly implement via sys and Cons_Proxy in Poly_Impl
391+
"""
392+
Returns a list of :class:`Constraint` of the polyhedron.
393+
394+
Note: the constraints space dim is not necessarily the ambient space dim of the poly.
395+
"""
390396
cdef Cons constraint_vector
391397
constraint_vector = self.thisptr[0].copy_cons()
392398
result = []
393399
cdef unsigned int index = constraint_vector.size() # hacky way to iterate over vectors
394400
for i in range(index):
395-
c = Constraint()
401+
c = Constraint(i)
396402
c.thisptr = new Con(constraint_vector[i])
397403
result.append(c)
398404
return result
399405

400406
def generators(self):
401407
"""
402-
Returns a list of :class:`PPliteGenerator`.
408+
Returns a list of :class:`PPliteGenerator`of the polyhedron.
403409
"""
404-
# Access constraints indirectly via copy_cons()
405-
# TODO: Properly implement via sys and Cons_Proxy in Poly_Impl
406410
cdef Gens generator_vector
407411
generator_vector = self.thisptr[0].copy_gens()
408412
result = []
@@ -414,8 +418,7 @@ cdef class NNC_Polyhedron(object):
414418
return result
415419

416420
def normalized_constraints(self):
417-
# TODO implement once Cons_Proxy is implemented.
418-
pass
421+
raise NotImplementedError
419422

420423
def num_min_constrains(self):
421424
return self.thisptr[0].num_min_cons()
@@ -461,6 +464,9 @@ cdef class NNC_Polyhedron(object):
461464
self.thisptr[0].set_empty()
462465

463466
def set_topology(self, topology):
467+
"""
468+
Sets the topology of the NNC polyhedron as either "closed" or "nnc".
469+
"""
464470
cdef Topol tt
465471
tt = string_to_Topol(topology)
466472
self.thisptr[0].set_topology(tt)
@@ -585,8 +591,9 @@ cdef class NNC_Polyhedron(object):
585591
v = (<Variable> variable).thisptr
586592
self.thisptr[0].unconstrain(v[0])
587593

588-
def unconstain_many(self, iter_of_var_or_index_set):
589-
pass
594+
def unconstain_many(self, iter_of_vars):
595+
for var in iter_of_vars:
596+
self.unconstain(var)
590597

591598
def intersection_assign(self, other_poly):
592599
if isinstance(other_poly, NNC_Polyhedron):
@@ -640,20 +647,32 @@ cdef class NNC_Polyhedron(object):
640647
den = Python_int_to_FLINT_Integer(denominator)
641648
self.thisptr[0].affine_preimage(var[0], expr, inhomo, den)
642649

643-
# TODO: Implement these
644-
def parallel_affine_image(self, args):
645-
pass
650+
def parallel_affine_image(self):
651+
raise NotImplementedError
646652

647653
def widing_assign(self, args):
648-
pass
654+
raise NotImplementedError
649655

650656
def time_elapse_assign(self, other_poly):
651657
if isinstance(other_poly, NNC_Polyhedron):
652658
y = (<NNC_Polyhedron> other_poly).thisptr
653659
self.thisptr[0].time_elapse_assign(y[0])
654660

655-
def minimize(self):
656-
self.thisptr[0].minimize()
661+
def split(self, constraint, topology):
662+
if isinstance(constraint, Constraint):
663+
con = (<Constraint> constraint).thisptr
664+
cdef Topol tt
665+
tt = string_to_Topol(topology)
666+
new_poly = NNC_Polyhedron()
667+
new_poly.thisptr = new Poly(self.thisptr[0].split(con[0], tt))
668+
return new_poly
669+
670+
def integral_split(self, constraint):
671+
if isinstance(constraint, Constraint):
672+
con = (<Constraint> constraint).thisptr
673+
new_poly = NNC_Polyhedron()
674+
new_poly.thisptr = new Poly(self.thisptr[0].integral_split(con[0]))
675+
return new_poly
657676

658677
def add_space_dimensions(self, dim_to_add, projection):
659678
cdef cppbool project
@@ -668,6 +687,26 @@ cdef class NNC_Polyhedron(object):
668687
else:
669688
raise TypeError("dim_to_add needs to be an ``int``.")
670689

690+
def concatenate_assign(self, poly):
691+
if isinstance(poly, NNC_Polyhedron):
692+
p = (<NNC_Polyhedron> poly).thisptr
693+
self.thisptr[0].concatenate_assign(p[0])
694+
695+
def remove_higher_space_dims(self, new_dim):
696+
cdef dim_type d
697+
d = Python_int_to_FLINT_Integer(new_dim)
698+
self.thisptr[0].remove_higher_space_dims(d)
699+
700+
def expand_space_dim(self, variable, dim_m):
701+
cdef dim_type d
702+
d = Python_int_to_FLINT_Integer(dim_m)
703+
if isinstance(variable, Variable):
704+
var = (<Variable> variable).thisptr
705+
self.thisptr[0].expand_space_dim(var[0], d)
706+
707+
def minimize(self):
708+
self.thisptr[0].minimize()
709+
671710
#####################################
672711
### Poly_Con_Rel and Poly_Gen_Rel ###
673712
#####################################
@@ -774,9 +813,6 @@ cdef class Polyhedron_Generator_Rel(object):
774813
def implies(self, Polyhedron_Generator_Rel y):
775814
return self.thisptr.implies(y.thisptr[0])
776815

777-
778-
# TODO Migrate helper functions to a helper function module.
779-
780816
#########################
781817
### Helper Functions ###
782818
#########################
@@ -799,24 +835,4 @@ cdef Spec_Elem string_to_Spec_Elem(s):
799835
if s == "universe":
800836
ss = Spec_Elem.UNIVERSE
801837
return ss
802-
raise ValueError("Unrecognized string {0}.".format(s))
803-
804-
805-
806-
807-
# cdef Poly_Con_Rel _new_Poly_Con_Rel(s):
808-
# if s == "nothing":
809-
# return PPlite_NOTHING
810-
811-
# raise ValueError("Unrecognized string {0}.".format(s))
812-
813-
# cdef _new_Poly_Con_Rel_Nothing():
814-
# cdef Poly_Con_Rel rel = Polyhedron_Constraint_Rel()
815-
# rel.thisptr = new NOTHING
816-
# return rel
817-
818-
819-
# cdef _new_Poly_Gen_Rel():
820-
# rel = Polyhedron_Generator_Rel()
821-
# rel.thisptr = new Poly_Gen_Rel()
822-
# return rel
838+
raise ValueError("Unrecognized string {0}.".format(s))

pplite/pplite_decl.pxd

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ cdef extern from "pplite/pplite.hh" namespace "pplite":
565565

566566

567567
# "pplite/Poly.hh"
568+
cdef cppclass Poly_Impl
568569
cdef cppclass Poly_Impl:
569570
# enum Status:
570571
# EMPTY
@@ -578,29 +579,34 @@ cdef extern from "pplite/pplite.hh" namespace "pplite":
578579
ctypedef struct gs "Sys<Gens>":
579580
pass
580581

582+
# This comes down to figuring out the namespace schematics
583+
# Cons_Proxy is an alias for Mater_Sys<Sys<Cons>, Poly_Impl>
584+
# using Cons_Proxy = Mater_Sys<Sys<Cons>, Poly_Impl>;
585+
# using is something that can be redone as a typedef
586+
# How does the using keyword play into the cython side in terms of alising?
587+
588+
# ctypedef struct Cons_Proxy: # "pplite::Mater_Sys<pplite::Poly_Impl::Sys<pplite::Cons>, pplite::Poly_Impl>": # Cons_Proxy
589+
# pass
581590

582-
# ctypedef struct Cons_Proxy "pplite::Mater_Sys<pplite::Poly_Impl::Sys<pplite::Cons>, pplite::Poly_Impl>": # Cons_Proxy
583-
# pass
584-
585-
# ctypedef struct Gens_Proxy "pplite::Mater_Sys<pplite::Poly_Impl::Sys<pplite::Gens>, pplite::Poly_Impl>": # Gens_Proxy
586-
# pass
587-
591+
# ctypedef srutct Gens_Proxy: # "pplite::Mater_Sys<pplite::Poly_Impl::Sys<pplite::Gens>, pplite::Poly_Impl>": # Gens_Proxy
592+
# pass
588593

594+
cdef cppclass Poly
589595
cdef cppclass Poly:
590-
Impl cppclass "pplite::Poly::Poly_Impl" # guess on how to alias this
596+
Impl cppclass "pplite::Poly_Impl" # guess on how to alias this
591597
Poly(dim_type d, Spec_Elem s, Topol t)
592598
Poly(dim_type d, Topol t, Spec_Elem s)
593599
Poly(Spec_Elem s, Topol t, dim_type d)
594600
Poly(Topol t, dim_type d, Spec_Elem s)
595601
Poly(Topol t, Spec_Elem s, dim_type d)
596602
Poly(Poly& y)
597603
Poly& operator=(Poly& y)
598-
Impl impl()
604+
Impl impl()
599605
# /* Types */
600-
ctypedef struct Cons_Proxy "Impl::Cons_Proxy": # using Impl::Cons_Proxy;
606+
ctypedef struct Cons_Proxy "Cons_Proxy": # using Impl::Cons_Proxy;
601607
pass # treat as container protocol, just try to iterate over it and don't worry too much about wrapping properly
602-
# these are c++ implementation details
603-
ctypedef struct Gens_Proxy "Impl::Gens_Proxy": # using Impl::Gens_Proxy;
608+
# # these are c++ implementation details
609+
ctypedef struct Gens_Proxy "Gens_Proxy": # using Impl::Gens_Proxy;
604610
pass
605611
# /* Predicates */
606612
cppbool is_necessarily_closed()
@@ -690,6 +696,7 @@ cdef extern from "pplite/pplite.hh" namespace "pplite":
690696

691697

692698
# PPlite/Poly_Rel.hh
699+
cdef cppclass Poly_Con_Rel
693700
cdef cppclass Poly_Con_Rel:
694701
ctypedef unsigned int Impl
695702
Poly_Con_Rel()
@@ -709,6 +716,7 @@ cdef extern from "pplite/pplite.hh" namespace "pplite":
709716
cdef Poly_Con_Rel PPlite_IS_INCLUDED "pplite::Poly_Con_Rel::is_included"()
710717
cdef Poly_Con_Rel PPlite_SATURATES "pplite::Poly_Con_Rel::saturates"()
711718

719+
cdef cppclass Poly_Gen_Rel
712720
cdef cppclass Poly_Gen_Rel:
713721
ctypedef unsigned int Impl
714722
Poly_Gen_Rel()

0 commit comments

Comments
 (0)