def simple_objectivelist_rule(rule): """ This is a decorator that translates None into ObjectiveList.End. This supports a simpler syntax in objective rules, though these can be more difficult to debug when errors occur. Example use: @simple_objectivelist_rule def O_rule(model, i, j): ... model.o = ObjectiveList(expr=simple_objectivelist_rule(...)) """ return rule_wrapper(rule, {None: ObjectiveList.End})
def simple_constraintlist_rule(rule): """ This is a decorator that translates None/True/False return values into ConstraintList.End/Constraint.Feasible/Constraint.Infeasible. This supports a simpler syntax in constraint rules, though these can be more difficult to debug when errors occur. Example use: @simple_constraintlist_rule def C_rule(model, i, j): ... model.c = ConstraintList(expr=simple_constraintlist_rule(...)) """ return rule_wrapper(rule, { None: ConstraintList.End, True: Constraint.Feasible, False: Constraint.Infeasible, })
def __init__(self, *args, **kwds): if "wrt" in kwds and "withrespectto" in kwds: raise TypeError( "Cannot specify both 'wrt' and 'withrespectto keywords") wrt = kwds.pop('wrt', None) wrt = kwds.pop('withrespectto', wrt) if wrt is None: # Check to be sure Integral is indexed by single # ContinuousSet and take Integral with respect to that # ContinuousSet if len(args) != 1: raise ValueError( "Integral indexed by multiple ContinuousSets. " "The desired ContinuousSet must be specified using the " "keyword argument 'wrt'") wrt = args[0] if type(wrt) is not ContinuousSet: raise ValueError( "Cannot take the integral with respect to '%s'. Must take an " "integral with respect to a ContinuousSet" % wrt) self._wrt = wrt loc = None for i, s in enumerate(args): if s is wrt: loc = i # Check that the wrt ContinuousSet is in the argument list if loc is None: raise ValueError( "The ContinuousSet '%s' was not found in the indexing sets " "of the Integral" % wrt.name) self.loc = loc # Remove the index that the integral is being expanded over arg = args[0:loc] + args[loc + 1:] # Check that if bounds are given bounds = kwds.pop('bounds', None) if bounds is not None: raise DAE_Error( "Setting bounds on integrals has not yet been implemented. " "Integrals may only be taken over an entire ContinuousSet") # Create integral expression and pass to the expression initialization intexp = kwds.pop('expr', None) intexp = kwds.pop('rule', intexp) if intexp is None: raise ValueError("Must specify an integral expression") _is_indexed = bool(len(arg)) def _trap_rule(rule, m, *a): ds = sorted(m.find_component(wrt.local_name)) return sum(0.5 * (ds[i + 1] - ds[i]) * (rule(m, *(a[0:loc] + (ds[i + 1], ) + a[loc:])) + rule(m, *(a[0:loc] + (ds[i], ) + a[loc:]))) for i in range(len(ds) - 1)) # Note that position_map is mapping arguments (block, *args), so # must be 1 more than len(args), and loc has to be offset by one kwds['rule'] = rule_wrapper( intexp, _trap_rule, positional_arg_map=(i for i in range(len(args) + 1) if i != loc + 1)) kwds.setdefault('ctype', Integral) Expression.__init__(self, *arg, **kwds)