Skip to content

Commit

Permalink
Trac #20351: sage.libs.ppl.MIP_Problem: Add support for integer varia…
Browse files Browse the repository at this point in the history
…bles

PPL's solver is a rational *MIP* solver.
Its support for integer variables should be exposed in Sage.

Reference: http://bugseng.com/products/ppl/documentation/user/ppl-
user-1.2-html/classParma__Polyhedra__Library_1_1MIP__Problem.html

For `sage.libs.ppl.MIP_Problem`, I think one just needs to add a wrapper
for this method:
{{{
void Parma_Polyhedra_Library::MIP_Problem::add_to_integer_space_dimensio
ns(const Variables_Set &i_vars)
}}}
and then a wrapper class for
[http://bugseng.com/products/ppl/documentation/user/ppl-
user-1.2-html/classParma__Polyhedra__Library_1_1Variables__Set.html
`Variables_Set`].

On another ticket (#20354), `PPLBackend` will be updated accordingly.

URL: http://trac.sagemath.org/20351
Reported by: mkoeppe
Ticket author(s): Matthias Koeppe
Reviewer(s): Dima Pasechnik
  • Loading branch information
Release Manager authored and vbraun committed Apr 5, 2016
2 parents 4489a4c + 9f35b65 commit 7067567
Showing 1 changed file with 190 additions and 0 deletions.
190 changes: 190 additions & 0 deletions src/sage/libs/ppl.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ cdef extern from "ppl.hh" namespace "Parma_Polyhedra_Library":
ctypedef size_t PPL_dimension_type "Parma_Polyhedra_Library::dimension_type"
ctypedef mpz_class PPL_Coefficient "Parma_Polyhedra_Library::Coefficient"
cdef cppclass PPL_Variable "Parma_Polyhedra_Library::Variable"
cdef cppclass PPL_Variables_Set "Parma_Polyhedra_Library::Variables_Set"
cdef cppclass PPL_Linear_Expression "Parma_Polyhedra_Library::Linear_Expression"
cdef cppclass PPL_Generator "Parma_Polyhedra_Library::Generator"
cdef cppclass PPL_Generator_System "Parma_Polyhedra_Library::Generator_System"
Expand All @@ -218,6 +219,16 @@ cdef extern from "ppl.hh" namespace "Parma_Polyhedra_Library":
bint OK()
PPL_dimension_type space_dimension()

cdef cppclass PPL_Variables_Set:
PPL_Variables_Set()
PPL_Variables_Set(PPL_Variable v)
PPL_Variables_Set(PPL_Variable v, PPL_Variable w)
PPL_dimension_type space_dimension()
void insert(PPL_Variable v)
size_t size()
void ascii_dump()
bint OK()

cdef cppclass PPL_Linear_Expression:
PPL_Linear_Expression()
PPL_Linear_Expression(PPL_Linear_Expression &e)
Expand Down Expand Up @@ -415,6 +426,7 @@ cdef extern from "ppl.hh" namespace "Parma_Polyhedra_Library":
void add_space_dimensions_and_embed(PPL_dimension_type m) except +ValueError
void add_constraint(PPL_Constraint &c) except +ValueError
void add_constraints(PPL_Constraint_System &cs) except +ValueError
void add_to_integer_space_dimensions(PPL_Variables_Set &i_vars) except +ValueError
void set_objective_function(PPL_Linear_Expression &obj) except +ValueError
void set_optimization_mode(PPL_Optimization_Mode mode)
PPL_Optimization_Mode optimization_mode()
Expand Down Expand Up @@ -460,6 +472,7 @@ cdef extern from "ppl_shim.hh":
### Forward declarations ###########################
cdef class _mutable_or_immutable(SageObject)
cdef class Variable(object)
cdef class Variables_Set(object)
cdef class Linear_Expression(object)
cdef class Generator(object)
cdef class Generator_System(_mutable_or_immutable)
Expand Down Expand Up @@ -998,6 +1011,34 @@ cdef class MIP_Problem(_mutable_or_immutable):
finally:
sig_off()

def add_to_integer_space_dimensions(self, Variables_Set i_vars):
"""
Sets the variables whose indexes are in set `i_vars` to be integer space dimensions.
EXAMPLES::
sage: from sage.libs.ppl import Variable, Variables_Set, Constraint_System, MIP_Problem
sage: x = Variable(0)
sage: y = Variable(1)
sage: cs = Constraint_System()
sage: cs.insert( x >= 0)
sage: cs.insert( y >= 0 )
sage: cs.insert( 3 * x + 5 * y <= 10 )
sage: m = MIP_Problem(2)
sage: m.set_objective_function(x + y)
sage: m.add_constraints(cs)
sage: i_vars = Variables_Set(x, y)
sage: m.add_to_integer_space_dimensions(i_vars)
sage: m.optimal_value()
3
"""
self.assert_mutable("The MIP_Problem is not mutable!");
sig_on()
try:
self.thisptr.add_to_integer_space_dimensions(i_vars.thisptr[0])
finally:
sig_off()

def set_objective_function(self, Linear_Expression obj):
"""
Sets the objective function to obj.
Expand Down Expand Up @@ -3775,6 +3816,155 @@ cdef class Variable(object):
return _make_Constraint_from_richcmp(self, other, op)


####################################################
### Variables_Set ##################################
####################################################

cdef class Variables_Set(object):
r"""
Wrapper for PPL's ``Variables_Set`` class.
A set of variables' indexes.
EXAMPLES:
Build the empty set of variable indexes::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: Variables_Set()
Variables_Set of cardinality 0
Build the singleton set of indexes containing the index of the variable::
sage: v123 = Variable(123)
sage: Variables_Set(v123)
Variables_Set of cardinality 1
Build the set of variables' indexes in the range from one variable to
another variable::
sage: v127 = Variable(127)
sage: Variables_Set(v123,v127)
Variables_Set of cardinality 5
"""

cdef PPL_Variables_Set *thisptr

def __cinit__(self, *args):
"""
The Cython constructor.
See :class:`Variables_Set` for documentation.
TESTS::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: Variables_Set()
Variables_Set of cardinality 0
"""
if len(args)==0:
self.thisptr = new PPL_Variables_Set()
elif len(args)==1:
v = <Variable?>args[0]
self.thisptr = new PPL_Variables_Set(v.thisptr[0])
elif len(args)==2:
v = <Variable?>args[0]
w = <Variable?>args[1]
self.thisptr = new PPL_Variables_Set(v.thisptr[0], w.thisptr[0])

def __dealloc__(self):
"""
The Cython destructor
"""
del self.thisptr

def OK(self):
"""
Checks if all the invariants are satisfied.
OUTPUT:
Boolean.
EXAMPLES::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: v123 = Variable(123)
sage: S = Variables_Set(v123)
sage: S.OK()
True
"""
return self.thisptr.OK()

def space_dimension(self):
r"""
Returns the dimension of the smallest vector space enclosing all the variables whose indexes are in the set.
OUPUT:
Integer.
EXAMPLES::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: v123 = Variable(123)
sage: S = Variables_Set(v123)
sage: S.space_dimension()
124
"""
return self.thisptr.space_dimension()

def insert(self, Variable v):
r"""
Inserts the index of variable `v` into the set.
EXAMPLES::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: S = Variables_Set()
sage: v123 = Variable(123)
sage: S.insert(v123)
sage: S.space_dimension()
124
"""
self.thisptr.insert(v.thisptr[0])

def ascii_dump(self):
r"""
Write an ASCII dump to stderr.
EXAMPLES::
sage: sage_cmd = 'from sage.libs.ppl import Variable, Variables_Set\n'
sage: sage_cmd += 'v123 = Variable(123)\n'
sage: sage_cmd += 'S = Variables_Set(v123)\n'
sage: sage_cmd += 'S.ascii_dump()\n'
sage: from sage.tests.cmdline import test_executable
sage: (out, err, ret) = test_executable(['sage', '-c', sage_cmd], timeout=100) # long time, indirect doctest
sage: print err # long time
<BLANKLINE>
variables( 1 )
123
"""
self.thisptr.ascii_dump()

def __repr__(self):
"""
Return a string representation.
OUTPUT:
String.
EXAMPLES::
sage: from sage.libs.ppl import Variable, Variables_Set
sage: S = Variables_Set()
sage: S.__repr__()
'Variables_Set of cardinality 0'
"""
return 'Variables_Set of cardinality {}'.format(self.thisptr.size())

####################################################
### Linear_Expression ##############################
####################################################
Expand Down

0 comments on commit 7067567

Please sign in to comment.