def __init__(self, problem=None, *args, **kwargs): super(Model, self).__init__(*args, **kwargs) if problem is None: self.problem = gurobipy.Model() self.problem.params.OutputFlag = 0 if self.name is not None: self.problem.setAttr('ModelName', self.name) self.problem.update() elif isinstance(problem, gurobipy.Model): self.problem = problem variables = [] for gurobi_variable in self.problem.getVars(): variables.append(Variable( gurobi_variable.getAttr("VarName"), lb=gurobi_variable.getAttr("lb"), ub=gurobi_variable.getAttr("ub"), problem=self, type=_GUROBI_VTYPE_TO_VTYPE[gurobi_variable.getAttr("vType")] )) super(Model, self)._add_variables(variables) constraints = [] for gurobi_constraint in self.problem.getConstrs(): sense = gurobi_constraint.Sense name = gurobi_constraint.getAttr("ConstrName") rhs = gurobi_constraint.RHS row = self.problem.getRow(gurobi_constraint) lhs = _unevaluated_Add( *[sympy.RealNumber(row.getCoeff(i)) * self.variables[row.getVar(i).VarName] for i in range(row.size())]) if sense == '=': constraint = Constraint(lhs, name=name, lb=rhs, ub=rhs, problem=self) elif sense == '>': constraint = Constraint(lhs, name=name, lb=rhs, ub=None, problem=self) elif sense == '<': constraint = Constraint(lhs, name=name, lb=None, ub=rhs, problem=self) else: raise ValueError('{} is not a valid sense'.format(sense)) constraints.append(constraint) super(Model, self)._add_constraints(constraints, sloppy=True) gurobi_objective = self.problem.getObjective() linear_expression = _unevaluated_Add( *[sympy.RealNumber(gurobi_objective.getCoeff(i)) * self.variables[gurobi_objective.getVar(i).VarName] for i in range(gurobi_objective.size())]) self._objective = Objective( linear_expression, problem=self, direction={1: 'min', -1: 'max'}[self.problem.getAttr('ModelSense')] ) else: raise TypeError("Provided problem is not a valid Gurobi model.") self.configuration = Configuration(problem=self, verbosity=0)
def _get_expression(self): if self.problem is not None: cplex_problem = self.problem.problem cplex_row = cplex_problem.linear_constraints.get_rows(self.name) variables = self.problem._variables expression = sympy.Add._from_args( [sympy.Mul._from_args((sympy.RealNumber(cplex_row.val[i]), variables[ind])) for i, ind in enumerate(cplex_row.ind)]) self._expression = expression return self._expression
def _sympy_converter(var_map, exp, target, expand_pow=False): rv = None assert isinstance(exp, sp.Expr) and target is not None if isinstance(exp, sp.Symbol): rv = var_map.get(exp.name, None) elif isinstance(exp, sp.Number): try: rv = RealVal(exp) if target == TARGET_Z3 else sp.RealNumber(exp) except: # Z3 parser error rep = sp.Float(exp, len(str(exp))) rv = RealVal(rep) elif isinstance(exp, sp.Add): # Add(exp_0, ...) rv = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) # eval this expression for e in exp.args[1:]: # add it to all other remaining expressions rv += _sympy_converter(var_map, e, target, expand_pow=expand_pow) elif isinstance(exp, sp.Mul): rv = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) for e in exp.args[1:]: rv *= _sympy_converter(var_map, e, target, expand_pow=expand_pow) elif isinstance(exp, sp.Pow): x = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) e = _sympy_converter(var_map, exp.args[1], target, expand_pow=expand_pow) if expand_pow: try: i = float(e.sexpr()) assert i.is_integer() i = int(i) - 1 rv = x for _ in range(i): rv *= x except: # fallback _sympy_converter(var_map, exp, target, expand_pow=False) else: rv = x**e assert rv is not None return rv
def _get_expression(self): if self.problem is not None: gurobi_problem = self.problem.problem gurobi_constraint = self._internal_constraint row = gurobi_problem.getRow(gurobi_constraint) terms = [] for i in range(row.size()): internal_var_name = row.getVar(i).VarName if internal_var_name == self.name + '_aux': continue variable = self.problem._variables[internal_var_name] coeff = sympy.RealNumber(row.getCoeff(i)) terms.append(sympy.Mul._from_args((coeff, variable))) sympy.Add._from_args(terms) self._expression = sympy.Add._from_args(terms) return self._expression
def _get_expression(self): if self.problem is not None: col_num = glp_get_num_cols(self.problem.problem) ia = intArray(col_num + 1) da = doubleArray(col_num + 1) nnz = glp_get_mat_row(self.problem.problem, self._index, ia, da) constraint_variables = [ self.problem._variables[glp_get_col_name( self.problem.problem, ia[i])] for i in range(1, nnz + 1) ] expression = sympy.Add._from_args([ sympy.Mul._from_args( (sympy.RealNumber(da[i]), constraint_variables[i - 1])) for i in range(1, nnz + 1) ]) self._expression = expression return self._expression
def __init__(self, problem=None, *args, **kwargs): super(Model, self).__init__(*args, **kwargs) self.configuration = Configuration() if problem is None: self.problem = glp_create_prob() glp_create_index(self.problem) if self.name is not None: glp_set_prob_name(self.problem, str(self.name)) else: try: self.problem = problem glp_create_index(self.problem) except TypeError: raise TypeError("Provided problem is not a valid GLPK model.") row_num = glp_get_num_rows(self.problem) col_num = glp_get_num_cols(self.problem) for i in range(1, col_num + 1): var = Variable(glp_get_col_name(self.problem, i), lb=glp_get_col_lb(self.problem, i), ub=glp_get_col_ub(self.problem, i), problem=self, type=_GLPK_VTYPE_TO_VTYPE[glp_get_col_kind( self.problem, i)]) # This avoids adding the variable to the glpk problem super(Model, self)._add_variables([var]) variables = self.variables for j in range(1, row_num + 1): ia = intArray(col_num + 1) da = doubleArray(col_num + 1) nnz = glp_get_mat_row(self.problem, j, ia, da) constraint_variables = [ variables[ia[i] - 1] for i in range(1, nnz + 1) ] # Since constraint expressions are lazily retrieved from the solver they don't have to be built here # lhs = _unevaluated_Add(*[da[i] * constraint_variables[i - 1] # for i in range(1, nnz + 1)]) lhs = 0 glpk_row_type = glp_get_row_type(self.problem, j) if glpk_row_type == GLP_FX: row_lb = glp_get_row_lb(self.problem, j) row_ub = row_lb elif glpk_row_type == GLP_LO: row_lb = glp_get_row_lb(self.problem, j) row_ub = None elif glpk_row_type == GLP_UP: row_lb = None row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_DB: row_lb = glp_get_row_lb(self.problem, j) row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_FR: row_lb = None row_ub = None else: raise Exception( "Currently, optlang does not support glpk row type %s" % str(glpk_row_type)) log.exception() if isinstance(lhs, int): lhs = sympy.Integer(lhs) elif isinstance(lhs, float): lhs = sympy.RealNumber(lhs) constraint_id = glp_get_row_name(self.problem, j) for variable in constraint_variables: try: self._variables_to_constraints_mapping[ variable.name].add(constraint_id) except KeyError: self._variables_to_constraints_mapping[ variable.name] = set([constraint_id]) super(Model, self)._add_constraints([ Constraint(lhs, lb=row_lb, ub=row_ub, name=constraint_id, problem=self, sloppy=True) ], sloppy=True) term_generator = ((glp_get_obj_coef(self.problem, index), variables[index - 1]) for index in range(1, glp_get_num_cols(problem) + 1)) self._objective = Objective(_unevaluated_Add(*[ _unevaluated_Mul(sympy.RealNumber(term[0]), term[1]) for term in term_generator if term[0] != 0. ]), problem=self, direction={ GLP_MIN: 'min', GLP_MAX: 'max' }[glp_get_obj_dir(self.problem)]) glp_scale_prob(self.problem, GLP_SF_AUTO)
def term_generator(): for index in range(1, glp_get_num_cols(self.problem.problem) + 1): coeff = glp_get_obj_coef(self.problem.problem, index) if coeff != 0.: yield (sympy.RealNumber(coeff), variables[index - 1])
def __init__(self, problem=None, *args, **kwargs): super(Model, self).__init__(*args, **kwargs) if problem is None: self.problem = cplex.Cplex() elif isinstance(problem, cplex.Cplex): self.problem = problem zipped_var_args = zip( self.problem.variables.get_names(), self.problem.variables.get_lower_bounds(), self.problem.variables.get_upper_bounds(), # self.problem.variables.get_types(), # TODO uncomment when cplex is fixed ) for name, lb, ub in zipped_var_args: var = Variable(name, lb=lb, ub=ub, problem=self) # Type should also be in there super(Model, self)._add_variables([ var ]) # This avoids adding the variable to the glpk problem zipped_constr_args = zip( self.problem.linear_constraints.get_names(), self.problem.linear_constraints.get_rows(), self.problem.linear_constraints.get_senses(), self.problem.linear_constraints.get_rhs()) variables = self._variables for name, row, sense, rhs in zipped_constr_args: constraint_variables = [variables[i - 1] for i in row.ind] # Since constraint expressions are lazily retrieved from the solver they don't have to be built here # lhs = _unevaluated_Add(*[val * variables[i - 1] for i, val in zip(row.ind, row.val)]) lhs = 0 if isinstance(lhs, int): lhs = sympy.Integer(lhs) elif isinstance(lhs, float): lhs = sympy.RealNumber(lhs) if sense == 'E': constr = Constraint(lhs, lb=rhs, ub=rhs, name=name, problem=self) elif sense == 'G': constr = Constraint(lhs, lb=rhs, name=name, problem=self) elif sense == 'L': constr = Constraint(lhs, ub=rhs, name=name, problem=self) elif sense == 'R': range_val = self.problem.linear_constraints.get_rhs(name) if range_val > 0: constr = Constraint(lhs, lb=rhs, ub=rhs + range_val, name=name, problem=self) else: constr = Constraint(lhs, lb=rhs + range_val, ub=rhs, name=name, problem=self) else: raise Exception( '%s is not a recognized constraint sense.' % sense) for variable in constraint_variables: try: self._variables_to_constraints_mapping[ variable.name].add(name) except KeyError: self._variables_to_constraints_mapping[ variable.name] = set([name]) super(Model, self)._add_constraints([constr], sloppy=True) try: objective_name = self.problem.objective.get_name() except cplex.exceptions.CplexSolverError as e: if 'CPLEX Error 1219:' not in str(e): raise e else: linear_expression = _unevaluated_Add(*[ _unevaluated_Mul(sympy.RealNumber(coeff), variables[index]) for index, coeff in enumerate( self.problem.objective.get_linear()) if coeff != 0. ]) try: quadratic = self.problem.objective.get_quadratic() except IndexError: quadratic_expression = Zero else: quadratic_expression = self._get_quadratic_expression( quadratic) self._objective = Objective( linear_expression + quadratic_expression, problem=self, direction={ self.problem.objective.sense.minimize: 'min', self.problem.objective.sense.maximize: 'max' }[self.problem.objective.get_sense()], name=objective_name) else: raise TypeError("Provided problem is not a valid CPLEX model.") self.configuration = Configuration(problem=self, verbosity=0)
import sympy as y from . import hz # driver parameters sD, Qts, Qms, Qes, Re, Le, Vas, fs, Xmax = y.symbols( 'sD Qts Qms Qes Re Le Vas fs Xmax') #cm2, unitless, l, hz, mm # T/S derived quantities Cms = Vas / (y.RealNumber(1.42) * sD**2 ) # 1.42 is adiabatic bulk modulus of air (fun fact) Mms = ((2 * y.pi * fs)**-2) / Cms Rms = (1 / Qms) * y.sqrt(Mms / Cms) Bl = y.sqrt(2 * y.pi * fs * Mms * Re / Qes) Mmd = Mms - (y.RealNumber(2.67) * (y.sqrt(1e-2 * sD) / y.pi)**3 * y.RealNumber(1.225e-3))
def _sympy_converter(var_map, exp, target, expand_pow=False): rv = None assert isinstance(exp, sp.Expr) and target is not None if isinstance(exp, sp.Symbol): rv = var_map.get(exp.name, None) elif isinstance(exp, sp.Number): try: rv = RealVal(exp) if isinstance(target, Z3Verifier) else sp.RealNumber(exp) except: # Z3 parser error rep = sp.Float(exp, len(str(exp))) rv = RealVal(rep) elif isinstance(exp, sp.Add): # Add(exp_0, ...) rv = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) # eval this expression for e in exp.args[1:]: # add it to all other remaining expressions rv += _sympy_converter(var_map, e, target, expand_pow=expand_pow) elif isinstance(exp, sp.Mul): rv = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) for e in exp.args[1:]: rv *= _sympy_converter(var_map, e, target, expand_pow=expand_pow) elif isinstance(exp, sp.Pow): x = _sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow) e = _sympy_converter(var_map, exp.args[1], target, expand_pow=expand_pow) if expand_pow: try: i = float(e.sexpr()) assert i.is_integer() i = int(i) - 1 rv = x for _ in range(i): rv *= x except: # fallback rv = _sympy_converter(var_map, exp, target, expand_pow=False) else: rv = x ** e elif isinstance(exp, sp.Max): x = _sympy_converter(var_map, exp.args[1], target, expand_pow=expand_pow) zero = exp.args[0] if target == Z3Verifier: rv = z3.If(x >= 0.0, x, 0.0) else: rv = dr.max(x, 0.0) elif isinstance(exp, sp.Heaviside): x = _sympy_converter(var_map, exp.args[0], target, expand_pow=False) if target == Z3Verifier: rv = z3.If(x > 0.0, 1.0, 0.0) else: rv = dr.if_then_else(x>0.0, 1.0, 0.0) elif isinstance(exp, sp.Function): # check various activation types ONLY FOR DREAL if isinstance(exp, sp.tanh): rv = dr.tanh(_sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow)) elif isinstance(exp, sp.sin): rv = dr.sin(_sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow)) elif isinstance(exp, sp.cos): rv = dr.cos(_sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow)) elif isinstance(exp, sp.exp): rv = dr.exp(_sympy_converter(var_map, exp.args[0], target, expand_pow=expand_pow)) else: ValueError('Term ' + str(exp) + ' not recognised') assert rv is not None return rv
def _populate_solver(self, reaction_list): """Populate attached solver with constraints and variables that model the provided reactions.""" constr_terms = dict() objective_terms = list() metabolites = {} for reaction in reaction_list: if reaction.reversibility: forward_variable = self.solver.interface.Variable( reaction._get_forward_id(), lb=0, ub=reaction._upper_bound) reverse_variable = self.solver.interface.Variable( reaction._get_reverse_id(), lb=0, ub=-1 * reaction._lower_bound) elif 0 == reaction.lower_bound and reaction.upper_bound == 0: forward_variable = self.solver.interface.Variable( reaction._get_forward_id(), lb=0, ub=0) reverse_variable = self.solver.interface.Variable( reaction._get_reverse_id(), lb=0, ub=0) elif reaction.lower_bound >= 0: forward_variable = self.solver.interface.Variable( reaction.id, lb=reaction._lower_bound, ub=reaction._upper_bound) reverse_variable = self.solver.interface.Variable( reaction._get_reverse_id(), lb=0, ub=0) elif reaction.upper_bound <= 0: forward_variable = self.solver.interface.Variable(reaction.id, lb=0, ub=0) reverse_variable = self.solver.interface.Variable( reaction._get_reverse_id(), lb=-1 * reaction._upper_bound, ub=-1 * reaction._lower_bound) self.solver._add_variable(forward_variable) self.solver._add_variable(reverse_variable) for metabolite, coeff in six.iteritems(reaction.metabolites): if metabolite.id in constr_terms: constr_terms[metabolite.id].append( sympy.Mul._from_args( [sympy.RealNumber(coeff), forward_variable])) else: constr_terms[metabolite.id] = [ sympy.Mul._from_args( [sympy.RealNumber(coeff), forward_variable]) ] metabolites[metabolite.id] = metabolite constr_terms[metabolite.id].append( sympy.Mul._from_args( [sympy.RealNumber(-1 * coeff), reverse_variable])) if reaction.objective_coefficient != 0.: objective_terms.append(reaction.objective_coefficient * reaction.flux_expression) for met_id, terms in six.iteritems(constr_terms): expr = sympy.Add._from_args(terms) try: self.solver.constraints[met_id] += expr except KeyError: self.solver._add_constraint(self.solver.interface.Constraint( expr, name=met_id, lb=0, ub=0), sloppy=True) objective_expression = sympy.Add(*objective_terms) if self.solver.objective is None: self.solver.objective = self.solver.interface.Objective( objective_expression, name='obj', direction='max') else: self.solver.objective.variables # TODO: remove this weird hack. Looks like some weird issue with lazy objective expressions in CPLEX and GLPK interface in optlang. self.solver.objective += objective_expression