def make_key_seq(self, keys, name): # INTERNAL Takes as input a candidate keys input and returns a valid key sequence used_name = name check_keys = True used_keys = [] if is_iterable(keys): if is_pandas_dataframe(keys): used_keys = keys.index.values elif has_len(keys): used_keys = keys elif is_iterator(keys): used_keys = list(keys) else: # TODO: make a test for this case. self.fatal( "Cannot handle iterable var keys: {0!s} : no len() and not an iterator", keys) # pragma: no cover elif is_int(keys) and keys >= 0: # if name is str and we have a size, disable automatic names used_name = None if name is str else name used_keys = range(keys) check_keys = False else: self.fatal( "Unexpected var keys: {0!s}, expecting iterable or integer", keys) # pragma: no cover if check_keys and len( used_keys ): # do not check truth value of used_keys: can be a Series! self._checker.typecheck_key_seq(used_keys) return used_name, used_keys
def _expand_bounds(self, keys, var_bound, default_bound, size, true_if_lb): ''' Converts raw bounds data (either LB or UB) to CPLEX-compatible bounds list. If lbs is None, this is the default, return []. If lbs is [] take the default again. If it is a number, build a list of size <size> with this number. If it is a list, use it if size ok (check numbers??), else try it as a function over keys. ''' if var_bound is None: # default lb is zero, default ub is infinity return [] elif is_number(var_bound): self._checker.typecheck_num(var_bound, caller='in variable bound') if true_if_lb: if var_bound == default_bound: return [] else: return [float(var_bound)] * size else: # ub if var_bound >= default_bound: return [] else: return [float(var_bound)] * size elif is_ordered_sequence(var_bound): nb_bounds = len(var_bound) if nb_bounds < size: # see how we can use defaults for those missing bounds self.fatal( "Variable bounds list is too small, expecting: %d, got: %d" % (size, nb_bounds)) else: return self._check_bounds(size, var_bound, default_bound, true_if_lb) elif is_iterator(var_bound): # unfold the iterator, as CPLEX needs a list return list(var_bound) elif isinstance(var_bound, dict): dict_bounds = [var_bound.get(k, default_bound) for k in keys] return self._check_bounds(size, dict_bounds, default_bound, true_if_lb) else: # try a function? try: fn_bounds = [var_bound(k) for k in keys] return self._check_bounds(size, fn_bounds, default_bound, true_if_lb) except TypeError: self._bad_bounds_fatal(var_bound) except Exception as e: # pragma: no cover self.fatal( "error calling function model bounds: {0!s}, error: {1!s}", var_bound, e)
def __init__(self, model, exprs, name=None): _IAdvancedExpr.__init__(self, model, name) if is_iterable(exprs) or is_iterator(exprs): self._exprs = exprs else: self._exprs = [model._lfactory._to_linear_operand(exprs)] # allocate xvars iff necessary self._xvars = [self._allocate_arg_var_if_necessary(e) for e in self._exprs]
def __init__(self, model, exprs, name=None): _FunctionalExpr.__init__(self, model, name) if is_iterable(exprs) or is_iterator(exprs): self._exprs = exprs else: self._exprs = [model._lfactory._to_linear_operand(exprs)] # allocate xvars iff necessary self._xvars = [ self._allocate_arg_var_if_necessary(expr, pos=e) for e, expr in enumerate(self._exprs, start=1) ]
def sumsq(self, sum_args): if is_iterable(sum_args): if is_iterator(sum_args): return self._sumsq(sum_args) elif isinstance(sum_args, dict): return self._sumsq(sum_args.values()) elif is_numpy_ndarray(sum_args): return self._sumsq(sum_args.flat) elif is_pandas_series(sum_args): return self._sumsq(sum_args.values) else: return self._sumsq(sum_args) elif is_number(sum_args): return sum_args ** 2 else: self._model.fatal("Model.sumsq() expects number/iterable/expression, got: {0!s}", sum_args)
def sum(self, sum_args): if is_iterator(sum_args): return self._sum_with_iter(sum_args) elif is_numpy_ndarray(sum_args): return self._sum_with_iter(sum_args.flat) elif is_pandas_series(sum_args): return self.sum(sum_args.values) elif isinstance(sum_args, dict): # handle dict: sum all values return self._sum_with_iter(itervalues(sum_args)) elif is_iterable(sum_args): return self._sum_with_seq(sum_args) elif is_number(sum_args): return sum_args else: return self._linear_factory._to_linear_expr(sum_args)
def __init__(self, model, exprs, name=None): _FunctionalExpr.__init__(self, model, name) assert is_iterable(exprs) or is_iterator(exprs) self._exprs = exprs # never allocate vars: arguments --are-- binary variables. self._xvars = exprs
def check_ordered_sequence(self, arg, caller, accept_iterator=True): # in some cases, we need an ordered sequence, if not the code won't crash # but may do unexpected things if not (is_ordered_sequence(arg) or (accept_iterator and is_iterator(arg))): self.fatal("{0}, got: {1!s}", caller, type(arg).__name__)
def check_ordered_sequence(self, arg, header): # in some cases, we need an ordered sequence, if not the code won't crash # but may do unexpected things if not is_ordered_sequence(arg) and not is_iterator(arg): self.fatal("{0}, got: {1!s}", header, type(arg).__name__)