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))
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)