def inside(self, rhs): self.to_expr() lhs_e = pop_expr() if isinstance(rhs, rangelist): return expr(ExprInModel(lhs_e, rhs.range_l)) elif isinstance(rhs, rng): rl = ExprRangelistModel() rl.add_range(ExprRangeModel(rhs.low, rhs.high)) return expr(ExprInModel(lhs_e, rl)) elif isinstance(rhs, list_t): return expr( ExprInModel( lhs_e, ExprRangelistModel([ExprFieldRefModel(rhs.get_model())]))) else: raise Exception("Unsupported 'inside' argument of type " + str(type(rhs)))
class rangelist(object): def __init__(self, *args): if len(args) == 0: raise Exception("Empty rangelist specified") self.range_l = ExprRangelistModel() for i in range(-1,-(len(args)+1), -1): a = args[i] if isinstance(a, tuple): # This needs to be a two-element array if len(a) != 2: raise Exception("Range specified with " + str(len(a)) + " elements is invalid. Two elements required") to_expr(a[0]) to_expr(a[1]) e1 = pop_expr() e0 = pop_expr() self.range_l.add_range(ExprRangeModel(e0, e1)) elif isinstance(a, rng): to_expr(a.low) to_expr(a.high) e1 = pop_expr() e0 = pop_expr() self.range_l.add_range(ExprRangeModel(e0, e1)) elif isinstance(a, list): for ai in a: to_expr(ai) eai = pop_expr() self.range_l.add_range(eai) else: to_expr(a) e = pop_expr() self.range_l.add_range(e) # self.range_l.rl.reverse() # This needs to be convertioble to a def __contains__(self, lhs): to_expr(lhs) return expr(ExprInModel(pop_expr(), self.range_l)) def __invert__(self): print("rangelist.__invert__")
def visit_constraint_dist(self, c): # We replace the dist constraint with an equivalent # set of hard and soft constraints scope = ConstraintDistScopeModel(c) ranges = ExprRangelistModel() for w in c.weights: if w.rng_rhs is not None: # two-value range ranges.add_range(ExprRangeModel(w.rng_lhs, w.rng_rhs)) else: # single value ranges.add_range(w.rng_lhs) # First, create an 'in' constraint to restrict # values to the appropriate value set in_c = ConstraintExprModel(ExprInModel(c.lhs, ranges)) scope.addConstraint(in_c) # Now, we need to add exclusion constraints for any # zero weights # (!w) -> (lhs != [val]) # (!w) -> (lns not in [rng]) for w in c.weights: if w.rng_rhs is not None: scope.addConstraint( ConstraintImpliesModel( ExprBinModel(w.weight, BinExprType.Eq, ExprLiteralModel(0, False, 8)), [ ConstraintExprModel( ExprUnaryModel( UnaryExprType.Not, ExprBinModel( ExprBinModel(c.lhs, BinExprType.Ge, w.rng_lhs), BinExprType.And, ExprBinModel(c.lhs, BinExprType.Le, w.rng_rhs)))) ])) else: scope.addConstraint( ConstraintImpliesModel( ExprBinModel(w.weight, BinExprType.Eq, ExprLiteralModel(0, False, 8)), [ ExprUnaryModel( UnaryExprType.Not, ExprBinModel(c.lhs, BinExprType.Eq, w.rng_lhs)) ])) # Form a list of non-zero weighted tuples of weight/range # Sort in ascending order weight_l = [] total_w = 0 for i, w in enumerate(c.weights): weight = int(w.weight.val()) total_w += weight if weight > 0: weight_l.append((weight, i)) weight_l.sort(key=lambda w: w[0]) seed_v = self.rng.randint(1, total_w) # Find the first range i = 0 while i < len(weight_l): seed_v -= weight_l[i][0] if seed_v <= 0: break i += 1 if i >= len(weight_l): i = len(weight_l) - 1 scope.target_range = weight_l[i][1] target_w = c.weights[weight_l[i][1]] dist_soft_c = None if target_w.rng_rhs is not None: dist_soft_c = ConstraintSoftModel( ExprBinModel( ExprBinModel(c.lhs, BinExprType.Ge, target_w.rng_lhs), BinExprType.And, ExprBinModel(c.lhs, BinExprType.Le, target_w.rng_rhs))) else: dist_soft_c = ConstraintSoftModel( ExprBinModel(c.lhs, BinExprType.Eq, target_w.rng_lhs)) # Give dist constraints a high priority to allow # them to override all user-defined soft constraints dist_soft_c.priority = 1000000 scope.set_dist_soft_c(dist_soft_c) self.override_constraint(scope)