示例#1
0
    def __init__(self, *args, **kwds):
        super(piecewise_dlog, self).__init__(*args, **kwds)

        breakpoints = self.breakpoints
        values = self.values

        if not is_positive_power_of_two(len(breakpoints) - 1):
            raise ValueError("The list of breakpoints must be "
                             "of length (2^n)+1 for some positive "
                             "integer n. Invalid length: %s" %
                             (len(breakpoints)))

        # create branching schemes
        L = log2floor(len(breakpoints) - 1)
        assert 2**L == len(breakpoints) - 1
        B_LEFT, B_RIGHT = self._branching_scheme(L)

        # create indexers
        polytopes = range(len(breakpoints) - 1)
        vertices = range(len(breakpoints))

        def polytope_verts(p):
            return xrange(p, p + 2)

        # create vars
        self.v = variable_dict()
        lmbda = self.v['lambda'] = variable_dict(((p, v), variable(lb=0))
                                                 for p in polytopes
                                                 for v in polytope_verts(p))
        y = self.v['y'] = variable_tuple(
            variable(domain=Binary) for i in range(L))

        # create piecewise constraints
        self.c = constraint_list()

        self.c.append(
            linear_constraint(
                variables=(self.input, ) + tuple(lmbda[p, v] for p in polytopes
                                                 for v in polytope_verts(p)),
                coefficients=(-1, ) + tuple(breakpoints[v] for p in polytopes
                                            for v in polytope_verts(p)),
                rhs=0))

        self.c.append(
            linear_constraint(
                variables=(self.output, ) + tuple(lmbda[p, v]
                                                  for p in polytopes
                                                  for v in polytope_verts(p)),
                coefficients=(-1, ) + tuple(values[v] for p in polytopes
                                            for v in polytope_verts(p))))
        if self.bound == 'ub':
            self.c[-1].lb = 0
        elif self.bound == 'lb':
            self.c[-1].ub = 0
        else:
            assert self.bound == 'eq'
            self.c[-1].rhs = 0

        self.c.append(
            linear_constraint(variables=tuple(lmbda.values()),
                              coefficients=(1, ) * len(lmbda),
                              rhs=1))

        clist = []
        for i in range(L):
            variables = tuple(lmbda[p, v] for p in B_LEFT[i]
                              for v in polytope_verts(p))
            clist.append(
                linear_constraint(variables=variables + (y[i], ),
                                  coefficients=(1, ) * len(variables) + (-1, ),
                                  ub=0))
        self.c.append(constraint_tuple(clist))
        del clist

        clist = []
        for i in range(L):
            variables = tuple(lmbda[p, v] for p in B_RIGHT[i]
                              for v in polytope_verts(p))
            clist.append(
                linear_constraint(variables=variables + (y[i], ),
                                  coefficients=(1, ) * len(variables) + (1, ),
                                  ub=1))
        self.c.append(constraint_tuple(clist))
示例#2
0
 def test_log2floor(self):
     self.assertEqual(util.log2floor(1), 0)
     self.assertEqual(util.log2floor(2), 1)
     self.assertEqual(util.log2floor(3), 1)
     self.assertEqual(util.log2floor(4), 2)
     self.assertEqual(util.log2floor(5), 2)
     self.assertEqual(util.log2floor(6), 2)
     self.assertEqual(util.log2floor(7), 2)
     self.assertEqual(util.log2floor(8), 3)
     self.assertEqual(util.log2floor(9), 3)
     self.assertEqual(util.log2floor(2**10), 10)
     self.assertEqual(util.log2floor(2**10 + 1), 10)
     self.assertEqual(util.log2floor(2**20), 20)
     self.assertEqual(util.log2floor(2**20 + 1), 20)
     self.assertEqual(util.log2floor(2**30), 30)
     self.assertEqual(util.log2floor(2**30 + 1), 30)
     self.assertEqual(util.log2floor(2**40), 40)
     self.assertEqual(util.log2floor(2**40 + 1), 40)