コード例 #1
0
ファイル: ppl_utils.py プロジェクト: videlec/surface_dynamics
def ppl_convert(P):
    r"""
    Convert a Sage polyhedron to a ppl polyhedron

    EXAMPLES::

        sage: from surface_dynamics.misc.ppl_utils import ppl_convert  # optional - pplpy
        sage: P = ppl_convert(Polyhedron(vertices=[(0,1,0),(1,0,1)], rays=[(0,0,1),[3,2,1]]))  # optional - pplpy
        sage: P.minimized_generators()  # optional - pplpy
        Generator_System {ray(0, 0, 1), point(0/1, 1/1, 0/1), point(1/1, 0/1, 1/1), ray(3, 2, 1)}
    """
    if isinstance(P, ppl.C_Polyhedron):
        return P
    gs = ppl.Generator_System()
    for v in P.vertices_list():
        gs.insert(ppl.point(sum(int(j) * ppl.Variable(i)
                                for i, j in enumerate(v))))
    for r in P.rays_list():
        gs.insert(ppl.ray(sum(int(j) * ppl.Variable(i)
                              for i, j in enumerate(r))))
    for l in P.lines_list():
        gs.insert(ppl.line(sum(int(j) * ppl.Variable(i)
                               for i, j in enumerate(l))))
    return ppl.C_Polyhedron(gs)
コード例 #2
0
    def rays(self):
        """
        **Description:**
        Returns the (not necessarily extremal) rays that generate the cone.

        **Arguments:**
        None.

        **Returns:**
        *(numpy.ndarray)* The list of rays that generate the cone.

        **Example:**
        We construct two cones and find their generating rays.
        ```python {3,6}
        c1 = Cone([[0,1],[1,1]])
        c2 = Cone(hyperplanes=[[0,1],[1,1]])
        c1.rays()
        # array([[0, 1],
        #        [1, 1]])
        c2.rays()
        # array([[ 1,  0],
        #        [-1,  1]])
        ```
        """
        if self._ext_rays is not None:
            return np.array(self._ext_rays)
        if self._rays is not None:
            return np.array(self._rays)
        if (self._ambient_dim >= 12
                and len(self._hyperplanes) != self._ambient_dim):
            print("Warning: This operation might take a while for d > ~12 "
                  "and is likely impossible for d > ~18.")
        cs = ppl.Constraint_System()
        vrs = [ppl.Variable(i) for i in range(self._ambient_dim)]
        for h in self.dual().extremal_rays():
            cs.insert(
                sum(h[i] * vrs[i] for i in range(self._ambient_dim)) >= 0)
        cone = ppl.C_Polyhedron(cs)
        rays = []
        for gen in cone.minimized_generators():
            if gen.is_ray():
                rays.append(tuple(int(c) for c in gen.coefficients()))
            elif gen.is_line():
                rays.append(tuple(int(c) for c in gen.coefficients()))
                rays.append(tuple(-int(c) for c in gen.coefficients()))
        self._rays = np.array(rays, dtype=int)
        self._dim = np.linalg.matrix_rank(self._rays)
        return np.array(self._rays)
コード例 #3
0
def ppl_cone(rays):
    r"""
    Convert the list ``rays`` into a ppl cone

    EXAMPLES::

        sage: from surface_dynamics.misc.ppl_utils import ppl_cone  # optional - pplpy
        sage: C = ppl_cone([(0,1,2),(1,1,1),(1,0,1)])   # optional - pplpy
        sage: C.minimized_generators()   # optional - pplpy
        Generator_System {point(0/1, 0/1, 0/1), ray(0, 1, 2), ray(1, 0, 1), ray(1, 1, 1)}
    """
    n = len(rays[0])
    gs = ppl.Generator_System(ppl_zero_point(n))
    for r in rays:
        gs.insert(ppl.ray(sum(j * ppl.Variable(i) for i, j in enumerate(r))))
    return ppl.C_Polyhedron(gs)
コード例 #4
0
def ppl_positive_cone(n):
    r"""
    Return the positive cone in R^n

    EXAMPLES::

        sage: from surface_dynamics.misc.ppl_utils import ppl_positive_cone # optional - pplpy
        sage: C = ppl_positive_cone(3)  # optional - pplpy
        sage: C.minimized_generators()  # optional - pplpy
        Generator_System {point(0/1, 0/1, 0/1), ray(0, 0, 1), ray(0, 1, 0), ray(1, 0, 0)}
    """
    gs = ppl.Generator_System(ppl_zero_point(n))
    l = [0] * n
    for i in range(n):
        gs.insert(ppl.ray(ppl.Variable(i)))
    return ppl.C_Polyhedron(gs)
コード例 #5
0
    def hyperplanes(self):
        """
        **Description:**
        Returns the inward-pointing normals to the hyperplanes that define the
        cone.

        **Arguments:**
        None.

        **Returns:**
        *(numpy.ndarray)* The list of inward-pointing normals to the
        hyperplanes that define the cone.

        **Example:**
        We construct two cones and find their hyperplane normals.
        ```python {3,6}
        c1 = Cone([[0,1],[1,1]])
        c2 = Cone(hyperplanes=[[0,1],[1,1]])
        c1.hyperplanes()
        # array([[ 1,  0],
        #        [-1,  1]])
        c2.hyperplanes()
        # array([[0, 1],
        #        [1, 1]])
        ```
        """
        if self._hyperplanes is not None:
            return np.array(self._hyperplanes)
        if self._ambient_dim >= 12 and len(self.rays()) != self._ambient_dim:
            print("Warning: This operation might take a while for d > ~12 "
                  "and is likely impossible for d > ~18.")
        gs = ppl.Generator_System()
        vrs = [ppl.Variable(i) for i in range(self._ambient_dim)]
        gs.insert(ppl.point(0))
        for r in self.extremal_rays():
            gs.insert(
                ppl.ray(sum(r[i] * vrs[i] for i in range(self._ambient_dim))))
        cone = ppl.C_Polyhedron(gs)
        hyperplanes = []
        for cstr in cone.minimized_constraints():
            hyperplanes.append(tuple(int(c) for c in cstr.coefficients()))
            if cstr.is_equality():
                hyperplanes.append(tuple(-int(c) for c in cstr.coefficients()))
        self._hyperplanes = np.array(hyperplanes, dtype=int)
        return np.array(self._hyperplanes)
コード例 #6
0
def DominationPolytope(i, LossMatrix):
    N, M = LossMatrix.shape

    # declare M ppl Variables
    p = [ppl.Variable(j) for j in range(M)]

    # declare polytope constraints
    cs = ppl.Constraint_System()

    # probabilies constraints on p
    cs.insert(sum(p[j] for j in range(M)) == 1)
    for j in range(M):
        cs.insert(p[j] >= 0)

    # strict Loss domination constraints
    Dom = scale_to_integers(domination_matrix(i, LossMatrix))

    for a in range(N):
        if a != i:
            # p is such that for any action a Loss[i,...]*p <= Loss[a,...]*p
            #print "Domination line:", Dom[a,...], "inequality:", sum( (Dom[a,j]*p[j] for j in range(M)) ) <= 0
            cs.insert(sum((Dom[a, j] * p[j] for j in range(M))) <= 0)

    return ppl.C_Polyhedron(cs)
コード例 #7
0
ファイル: ppl_py.py プロジェクト: fcristini/PPLite
#!/usr/bin/python
# Copyright (C) 2001-2010 Roberto Bagnara <*****@*****.**>
# Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
#
# This file is part of the Parma Polyhedra Library (PPL).
#
# The PPL is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# The PPL is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
#
# For the most up-to-date information see the Parma Polyhedra Library
# site: http://bugseng.com/products/ppl/ .

import ppl

var = ppl.Variable(4)
print var
コード例 #8
0
def parma_enumerate_vertices(A_ineq, b_ineq, A_eq=None, b_eq=None):
    """
    Iterator over extreme points of polytope defined by linear equalities
    and inequalities, A_ineq x <= b_ineq, A_eq x = b_eq.

    This uses the Parma Polyhedral Library (PPL). Because PPL expects all
    data to be rational, we enforce that inequalities and equalities are
    specified by integer-valued matrices.

    Parameters
    ----------
    A_ineq : np.array
        Inequalities matrix. Data type should be int,
        shape should be (num_inequalities x num_variables)
    b_ineq : np.array
        Inequalities values. Data type should be int,
        shape should be (num_inequalities)
    A_eq : np.array
        Equalities matrix. Data type should be int,
        shape should be (num_equalities x num_variables)
    b_eq : np.array
        Equalities values. Data type should be int,
        shape should be (num_equalities)
    """

    try:
        import ppl
    except ImportError:
        raise Exception("""
This method requires the Parma Polyhedra Library (PPL) library to
be installed. Normally, this can be done with
   pip3 install cysignals gmpy2
   pip3 install pplpy
Please see https://gitlab.com/videlec/pplpy for more information.
""")

    def get_num_cons(A, b):
        # Check data for validity and return number of constraints
        if A is None:
            assert (b is None or len(b) == 0)
            num_cons = 0
        else:
            assert (isinstance(A, np.ndarray))
            assert (isinstance(b, np.ndarray))
            assert (np.issubdtype(A.dtype, np.integer))
            assert (np.issubdtype(b.dtype, np.integer))
            num_cons = A.shape[0]
            assert (num_cons == len(b))
        return num_cons

    num_ineq_cons = get_num_cons(A_ineq, b_ineq)
    num_eq_cons = get_num_cons(A_eq, b_eq)

    if num_eq_cons == 0 and num_ineq_cons == 0:
        raise Exception(
            "Must specify at least one inequality or equality constrants")

    if num_eq_cons > 0 and num_ineq_cons > 0:
        assert (A_eq.shape[1] == A_ineq.shape[1])

    num_vars = (A_eq if num_eq_cons > 0 else A_ineq).shape[1]

    ppl_vars = [ppl.Variable(i) for i in range(num_vars)]

    cs = ppl.Constraint_System()
    for rowndx in range(num_ineq_cons):
        if np.all(A_ineq[rowndx] == 0):
            if b_ineq[rowndx] < 0:
                raise Exception(
                    'Inequality constraint {} involves no variables and is unsatisfiable'
                    .format(rowndx))
            else:
                continue  # trivial constraint

        lhs = sum([
            coef * ppl_vars[i] for i, coef in enumerate(A_ineq[rowndx])
            if coef != 0
        ])
        cs.insert(lhs <= b_ineq[rowndx])

    for rowndx in range(num_eq_cons):
        if np.all(A_eq[rowndx] == 0):
            if b_eq[rowndx] != 0:
                raise Exception(
                    'Equality constraint {} involves no variables and is unsatisfiable'
                    .format(rowndx))
            else:
                continue  # trivial constraint

        lhs = sum([
            coef * ppl_vars[i] for i, coef in enumerate(A_eq[rowndx])
            if coef != 0
        ])
        cs.insert(lhs == b_eq[rowndx])

    # convert linear inequalities into a list of extreme points
    poly_from_constraints = ppl.C_Polyhedron(cs)
    all_generators = poly_from_constraints.minimized_generators()

    for p in all_generators:
        if not p.is_point():
            raise Exception(
                'Returned solution not a point: {}. '.format(p) +
                'Typically this means that linear constraints specify a cone, not a polytope'
            )

        # Convert a solution vector in ppl format to a numpy array
        x = np.fromiter(p.coefficients(), dtype='double')
        x = x / float(p.divisor())
        yield x
コード例 #9
0
    def is_solid(self, backend=None, c=0.01, verbose=0):
        """
        **Description:**
        Returns True if the cone is solid, i.e. if it is full-dimensional.

        :::note
        If the generating rays are known then this can simply be checked by
        computing the dimension of the linear space that they span. However,
        when only the hyperplane inequalities are known this can be a difficult
        problem. When using PPL as the backend, the convex hull is explicitly
        constructed and checked. The other backends try to solve an
        optimization problem inside the stretched cone, which fails if the cone
        is not solid. The latter approach is much faster, but there can be
        extremely narrow cones where the optimization fails and this function
        returns a false negative. Mosek is recommended when using such
        extremely narrow cones.
        :::

        **Arguments:**
        - `backend` *(str, optional)*: Specifies which backend to use.
          Available options are "ppl", "ortools", and any backends available
          for the [`tip_of_stretched_cone`](#tip_of_stretched_cone)
          function. If not specified, it tries all available backends.
        - `c` *(float, optional, default=0.01)*: A number used to create
          the stretched cone and try to find the tip. This is ignored when
          using PPL as the backend.
        - `verbose` *(int, optional, default=0)*: The verbosity level.
          - verbose = 0: Do not print anything.
          - verbose = 1: Print warnings when optimizers fail.

        **Returns:**
        *(bool)* The truth value of the cone being solid.

        **Example:**
        We construct two cones and check if they are solid.
        ```python {3,5}
        c1 = Cone([[1,0],[0,1]])
        c2 = Cone([[1,0,0],[0,1,0]])
        c1.is_solid()
        # True
        c2.is_solid()
        # False
        ```
        """
        if self._is_solid is not None:
            return self._is_solid
        if self._rays is not None:
            return np.linalg.matrix_rank(self._rays) == self._ambient_dim
        if backend is None:
            backend = ("mosek" if config.mosek_is_activated() else "ortools")
        if backend == "ppl":
            cs = ppl.Constraint_System()
            vrs = [ppl.Variable(i) for i in range(self._ambient_dim)]
            for h in self._hyperplanes:
                cs.insert(
                    sum(h[i] * vrs[i] for i in range(self._ambient_dim)) >= 0)
            cone = ppl.C_Polyhedron(cs)
            self._is_solid = cone.affine_dimension() == self._ambient_dim
            return self._is_solid
        if backend == "ortools":
            hp = self._hyperplanes.tolist()
            solve_ctr = 0
            while solve_ctr < 10:
                obj_vec = np.dot(np.random.random(size=len(hp)), hp)
                solver = pywraplp.Solver(
                    "find_pt", pywraplp.Solver.GLOP_LINEAR_PROGRAMMING)
                obj = solver.Objective()
                var = []
                for i in range(self._ambient_dim):
                    var.append(
                        solver.NumVar(-solver.infinity(), solver.infinity(),
                                      f"x_{i}"))
                    obj.SetCoefficient(var[-1], obj_vec[i])
                obj.SetMinimization()
                cons_list = []
                for v in hp:
                    cons_list.append(solver.Constraint(c, solver.infinity()))
                    for j in range(self._ambient_dim):
                        cons_list[-1].SetCoefficient(var[j], v[j])
                status = solver.Solve()
                if status in (solver.FEASIBLE, solver.OPTIMAL):
                    self._is_solid = True
                    return self._is_solid
                elif status == solver.INFEASIBLE:
                    self._is_solid = False
                    return self._is_solid
                else:
                    if verbose >= 1:
                        print(
                            f"Solver returned status: {status}. Trying again.")
                    solve_ctr += 1
            if verbose >= 1:
                print("Linear solver failed too many times. "
                      "Assuming problem infeasible.")
            self._is_solid = False
            return self._is_solid
        if backend in ("all", "mosek", "cvxopt"):
            opt_res = None
            try:
                opt_res = self.tip_of_stretched_cone(c,
                                                     backend=backend,
                                                     verbose=verbose)
            except:
                pass
            self._is_solid = opt_res is not None
            return self._is_solid
        else:
            backends = ["ppl", "ortools", "all", "mosek", "cvxopt"]
            raise Exception(f"Available options for backends are: {backends}")