Source code for docplex.mp.model_reader

# --------------------------------------------------------------------------
# Source file provided under Apache License, Version 2.0, January 2004,
# http://www.apache.org/licenses/
# (c) Copyright IBM Corp. 2015, 2016
# --------------------------------------------------------------------------

import os
import time

# docplex
from docplex.mp.model import Model
from docplex.mp.utils import DOcplexException, MockIterable
from docplex.mp.environment import Environment

from docplex.mp.params.cplex_params import get_params_from_cplex_version
from docplex.mp.constants import ComparisonType
from docplex.mp.constr import LinearConstraint

from docplex.mp.cplex_adapter import CplexAdapter
from docplex.mp.cplex_engine import CplexEngine

from docplex.mp.quad import VarPair


[docs]class ModelReaderError(DOcplexException): pass
class _CplexReaderFileContext(object): def __init__(self, filename, read_method=None): self._cplex = None self._filename = filename self._read_method = read_method or ["read"] def __enter__(self): self.cpx_adapter = CplexAdapter() cpx = self.cpx_adapter.cpx # no output from CPLEX cpx.set_results_stream(None) cpx.set_log_stream(None) cpx.set_warning_stream(None) cpx.set_error_stream(None) self_read_fn = cpx for m in self._read_method: self_read_fn = self_read_fn.__getattribute__(m) try: self_read_fn(self._filename) self._cplex = cpx return self.cpx_adapter except self.cpx_adapter.CplexError as cpx_e: # pragma: no cover # delete cplex instance del cpx raise ModelReaderError("*CPLEX error {0!s} reading file {1} - exiting".format(cpx_e, self._filename)) # noinspection PyUnusedLocal def __exit__(self, exc_type, exc_val, exc_tb): cpx = self._cplex if cpx is not None: del cpx self._cplex = None # def compute_full_dotf(mdl, coefs, constant=0): # def coef_fn(dvx): # return coefs[dvx] # # lfactory = mdl._lfactory # terms_dict = lfactory._new_term_dict() # for dv in mdl.iter_variables(): # coef = coef_fn(dv.index) # if coef: # terms_dict[dv] = coef # linear_expr = lfactory.linear_expr(terms_dict, constant=constant, safe=True) # return linear_expr def compute_full_dot(mdl, coefs, constant=0): # compute a scalar product, with possible zeros as coefs lfactory = mdl._lfactory terms_dict = lfactory._new_term_dict() for dv, k in zip(mdl.iter_variables(), coefs): if k: terms_dict[dv] = k linear_expr = lfactory.linear_expr(terms_dict, constant=constant, safe=True) return linear_expr # noinspection PyArgumentList
[docs]class ModelReader(object): """ This class is used to read models from CPLEX files (e.g. SAV, LP, MPS) This class requires CPLEX runtime, otherwise an exception is raised. Example: Use class method ``read`` to read a model file. >>> m = ModelReader.read('mymodel.lp', ignore_names=True) reads a model while ignoring all names. Global function ``read_model`` is a synonym for ``ModelReader.read``, and is the preferred way to read model files. """ @staticmethod def _build_linear_expr_from_sparse_pair(lfactory, var_map, cpx_sparsepair): terms = {var_map[ix]: k for ix, k in zip(cpx_sparsepair.ind, cpx_sparsepair.val)} expr = lfactory.linear_expr(arg=terms, safe=True) return expr _sense2comp_dict = {'L': ComparisonType.LE, 'E': ComparisonType.EQ, 'G': ComparisonType.GE} # noinspection PyDefaultArgument @classmethod def parse_sense(cls, cpx_sense, sense_dict=_sense2comp_dict): return sense_dict.get(cpx_sense)
[docs] @classmethod def read_prm(cls, filename): """ Reads a CPLEX PRM file. Reads a CPLEX parameters file and returns a DOcplex parameter group instance. This parameter object can be used in a solve(). Args: filename: a path string Returns: A `RootParameterGroup object`, if the read operation succeeds, else None. """ # TODO: Clean up - now creating an adapter raise importError if CPLEX not found # if not Cplex: # pragma: no cover # raise RuntimeError("ModelReader.read_prm() requires CPLEX runtime.") with _CplexReaderFileContext(filename, read_method=["parameters", "read_file"]) as adapter: cpx = adapter.cpx if cpx: # raw parameters params = get_params_from_cplex_version(cpx.get_version()) for param in params: try: cpx_value = cpx._env.parameters._get(param.cpx_id) if cpx_value != param.default_value: param.set(cpx_value) except adapter.CplexError: # pragma: no cover pass return params else: # pragma: no cover return None
@staticmethod def _safe_call_get_names(cpx_adapter, get_names_fn, fallback_names=None): # cplex crashes when calling get_names on some files (e.g. SAV) # in this case filter out error 1219 # and return a fallback list with None or "" try: names = get_names_fn() return names # except TypeError: # print("** type error ignored in call to {0}".format(get_names_fn.__name__)) # return fallback_names or [] except cpx_adapter.CplexSolverError as cpxse: # pragma: no cover errcode = cpxse.args[2] # when all indicators have no names, cplex raises this error # CPLEX Error 1219: No names exist. if errcode == 1219: return fallback_names or [] else: # this is something else raise @classmethod def _read_cplex(cls, filename, datacheck=None, silent=True): cpx_adapter = CplexAdapter() cpx = cpx_adapter.cpx # no warnings if silent: cpx.set_results_stream(None) cpx.set_log_stream(None) cpx.set_warning_stream(None) cpx.set_error_stream(None) # remove messages about names try: if datacheck is not None: assert datacheck in {0,1,2} cpx.parameters.read.datacheck.set(datacheck) t0 = time.time() cpx.read(filename) t1 = time.time() - t0 if Model.is_docplex_debug() and t1 >= 0.1: print(f"-- cplex read time={t1:.1f}s") return cpx_adapter except cpx_adapter.CplexError as cpx_e: raise ModelReaderError("*CPLEX error {0!s} reading file {1} - exiting".format(cpx_e, filename)) @classmethod def _make_expr_from_varmap_coefs_dict(cls, lfactory, varmap, var_indices, coefs, offset=0): terms_dict = {varmap.get(dvx): k for dvx, k in zip(var_indices, coefs)} return lfactory.linear_expr(arg=terms_dict, constant=offset, safe=True) @classmethod def _make_expr_from_var_coef_seq_dict(cls, lfactory, varmap, var_coefs, constant=0): terms_dict = {varmap.get(dvx): k for dvx, k in var_coefs} return lfactory.linear_expr(arg=terms_dict, constant=constant, safe=True) @classmethod def _make_expr_from_varmap_coefs_nodict(cls, lfactory, varmap, var_indices, coefs, offset=0): terms_dict = lfactory._new_term_dict() for dvx, k in zip(var_indices, coefs): dv = varmap.get(dvx) if dv is not None: terms_dict[dv] = k return lfactory.linear_expr(arg=terms_dict, constant=offset, safe=True) @classmethod def _make_expr_from_var_coef_seq_nodict(cls, lfactory, varmap, var_coefs, constant=0): terms_dict = lfactory._new_term_dict() for dvx, k in var_coefs: dv = varmap.get(dvx) if dv is not None: terms_dict[dv] = k return lfactory.linear_expr(arg=terms_dict, constant=constant, safe=True) @classmethod def _make_expr_from_varmap_coefs(cls, lfactory, varmap, var_indices, coefs, offset=0): if Environment.env_is_python36: terms_dict = {varmap.get(dvx): k for dvx, k in zip(var_indices, coefs)} else: terms_dict = lfactory._new_term_dict() for dvx, k in zip(var_indices, coefs): dv = varmap.get(dvx) if dv is not None: terms_dict[dv] = k return lfactory.linear_expr(arg=terms_dict, constant=offset, safe=True)
[docs] @classmethod def read(cls, filename, model_name=None, verbose=False, model_class=None, **kwargs): """ Reads a model from a CPLEX export file. Accepts all formats exported by CPLEX: LP, SAV, MPS. If an error occurs while reading the file, the message of the exception is printed and the function returns None. Args: filename: The file to read. model_name: An optional name for the newly created model. If None, the model name will be the path basename. verbose: An optional flag to print informative messages, default is False. model_class: An optional class type; must be a subclass of Model. The returned model is built using this model_class and the keyword arguments kwargs, if any. By default, the model class is :class:`docplex.mp.model.Model`. kwargs: A dict of keyword-based arguments that are used when creating the modelpassed to the model constructor. Example: `m = read_model("c:/temp/foo.mps", model_name="docplex_foo", ignore_names=True)` reads a ,odel from file "c:/temp/foo.mps", sets its name to "docplex_foo", and discard all names. Returns: An instance of Model, or None if an exception is raised. See Also: :class:`docplex.mp.model.Model` """ if not os.path.exists(filename): raise IOError("* file not found: {0}".format(filename)) # extract basename if model_name: name_to_use = model_name else: basename = os.path.basename(filename) if '.' not in filename: # pragma: no cover raise RuntimeError('ModelReader.read_model(): path has no extension: {}'.format(filename)) dotpos = basename.find(".") if dotpos > 0: name_to_use = basename[:dotpos] else: # pragma: no cover name_to_use = basename model_class = model_class or Model if 0 == os.stat(filename).st_size: print("* file is empty: {0} - exiting".format(filename)) return model_class(name=name_to_use, **kwargs) data_check = kwargs.pop('datacheck', None) if verbose: print("-> CPLEX starts reading file: {0}".format(filename)) cpx_adapter = cls._read_cplex(filename, datacheck=data_check) cpx = cpx_adapter.cpx if verbose: print("<- CPLEX finished reading file: {0}".format(filename)) if not cpx: # pragma: no cover return None final_output_level = kwargs.get("output_level", "info") debug_read = kwargs.get("debug", False) final_agent = kwargs.get('agent', 'cplex') use_new = kwargs.pop('use_new', True) try: # force no tck if 'checker' in kwargs: final_checker = kwargs['checker'] else: final_checker = 'default' # build the model with no checker, then restore final_checker in the end. kwargs['checker'] = 'off' kwargs['agent'] = 'zero' ignore_names = kwargs.get('ignore_names', False) # ------------- if Environment.env_is_python36: make_terms_fn = cls._make_expr_from_varmap_coefs_dict make_terms_seq_fn = cls._make_expr_from_var_coef_seq_dict else: make_terms_fn = cls._make_expr_from_varmap_coefs_nodict make_terms_seq_fn = cls._make_expr_from_var_coef_seq_nodict mdl = model_class(name=name_to_use, **kwargs) if data_check is not None: mdl.parameters.read.datacheck = data_check mdl._provenance = filename lfactory = mdl._lfactory qfactory = mdl._qfactory mdl.set_quiet() # output level set to ERROR vartype_cont = mdl.continuous_vartype vartype_map = {'B': mdl.binary_vartype, 'I': mdl.integer_vartype, 'C': mdl.continuous_vartype, 'S': mdl.semicontinuous_vartype} def cpx_type_to_docplex_type(cpxt): return vartype_map.get(cpxt, vartype_cont) # 1 upload variables cpx_nb_vars = cpx.variables.get_num() if verbose: print("-- uploading {0} variables...".format(cpx_nb_vars)) cpx_env_e = cpx._env._e cpx_lp = cpx._lp has_non_default_lb = cpx_adapter.has_non_default_lb has_non_default_ub = cpx_adapter.has_non_default_ub has_name = cpx_adapter.has_name cpx_var_names = [] if not ignore_names: if not has_name or has_name(cpx_env_e, cpx_lp, 0, cpx_nb_vars - 1): cpx_var_names = cls._safe_call_get_names(cpx_adapter, cpx.variables.get_names) # check whether all varianbles have same type, it's worth it. unique_type = None docplex_vartypes = None if cpx._is_MIP(): cpx_types = cpx.variables.get_types() first_cpxtype = cpx_types[0] if all(cpxt == first_cpxtype for cpxt in cpx_types): unique_type = cpx_type_to_docplex_type(first_cpxtype) else: # docplex_vartypes = [cpx_type_to_docplex_type(cpxt) for cpxt in cpx_types] def kth_vartype(k): return cpx_type_to_docplex_type(cpx_types[k]) docplex_vartypes = MockIterable(size=cpx_nb_vars, fn_k=kth_vartype) else: unique_type = vartype_cont if use_new and has_non_default_lb and not has_non_default_lb(cpx_env_e, cpx_lp, 0, cpx_nb_vars - 1): cpx_var_lbs = [] else: # either we have no fast predicate or we dont use it. cpx_var_lbs = cpx.variables.get_lower_bounds() # we have no predicate, so we might try to avoid building a large list?? if not has_non_default_lb and not any(cpx_var_lbs): # all equal 0 cpx_var_lbs = [] if use_new and has_non_default_ub and not has_non_default_ub(cpx_env_e, cpx_lp, 0, cpx_nb_vars - 1): cpx_var_ubs = [] else: cpx_var_ubs = cpx.variables.get_upper_bounds() if not has_non_default_ub and all(cpxu >= 1e+20 for cpxu in cpx_var_ubs): cpx_var_ubs = [] # if no names, None is fine. model_varnames = cpx_var_names or None model_lbs = cpx_var_lbs model_ubs = cpx_var_ubs # vars if unique_type: model_vars = lfactory.new_var_list(var_container=None, key_seq=range(cpx_nb_vars), vartype=unique_type, lb=model_lbs, ub=model_ubs, name=model_varnames, _safe_bounds=True, _safe_names=True ) else: assert docplex_vartypes model_vars = lfactory.new_multitype_var_list(cpx_nb_vars, docplex_vartypes, model_lbs, model_ubs, model_varnames) # inverse map from indices to docplex vars cpx_var_index_to_docplex = {v: model_vars[v] for v in range(cpx_nb_vars)} # 2. upload linear constraints and ranges (mixed in cplex) cpx_linearcts = cpx.linear_constraints nb_linear_cts = cpx_linearcts.get_num() all_rhs = cpx_linearcts.get_rhs() all_senses = cpx_adapter.getsense(cpx_env_e, cpx_lp, 0, nb_linear_cts - 1) if 'R' in all_senses: all_range_values = cpx_linearcts.get_range_values() else: # do not query ranges if no R in senses... all_range_values = [] cpx_ctnames = [] if ignore_names else cls._safe_call_get_names(cpx_adapter, cpx_linearcts.get_names) def make_constant_expr(k): return lfactory.constant_expr(k, safe_number=True) if verbose: print("-- uploading {0} linear constraints...".format(nb_linear_cts)) def upload_rows(row_iter): cts_ = [] for c, (indices, coefs) in enumerate(row_iter): sense = all_senses[c] rhs = all_rhs[c] ctname = cpx_ctnames[c] if cpx_ctnames else None expr = make_terms_fn(lfactory, cpx_var_index_to_docplex, indices, coefs) if sense == 'R': # no use of querying range vars if no R constraints range_val = all_range_values[c] # rangeval can be negative !!! issue 52 if range_val >= 0: range_lb = rhs range_ub = rhs + range_val else: range_ub = rhs range_lb = rhs + range_val rgct = lfactory.new_range_constraint(lb=range_lb, ub=range_ub, expr=expr, name=ctname, check_feasible=False) cts_.append(rgct) else: op = cls.parse_sense(sense) rhs_expr = make_constant_expr(rhs) ct = LinearConstraint(mdl, expr, op, rhs_expr, ctname) cts_.append(ct) return cts_ if nb_linear_cts: fast_get_rows_tuple = cpx_adapter.fast_get_row_tuples if fast_get_rows_tuple: with fast_get_rows_tuple(cpx_env_e, cpx_lp) as rowgen: deferred_cts = upload_rows(rowgen) else: all_rows = cpx_adapter.fast_get_rows(cpx) deferred_cts = upload_rows(all_rows) # add constraint as a block lfactory._post_constraint_block(posted_cts=deferred_cts) # 3. upload Quadratic constraints cpx_quadraticcts = cpx.quadratic_constraints nb_quadratic_cts = cpx_quadraticcts.get_num() if nb_quadratic_cts: all_rhs = cpx_quadraticcts.get_rhs() all_linear_nb_non_zeros = cpx_quadraticcts.get_linear_num_nonzeros() all_linear_components = cpx_quadraticcts.get_linear_components() all_quadratic_nb_non_zeros = cpx_quadraticcts.get_quad_num_nonzeros() all_quadratic_components = cpx_quadraticcts.get_quadratic_components() all_senses = cpx_quadraticcts.get_senses() cpx_ctnames = [] if ignore_names else cls._safe_call_get_names(cpx_adapter, cpx_quadraticcts.get_names) for c in range(nb_quadratic_cts): rhs = all_rhs[c] linear_nb_non_zeros = all_linear_nb_non_zeros[c] linear_component = all_linear_components[c] quadratic_nb_non_zeros = all_quadratic_nb_non_zeros[c] quadratic_component = all_quadratic_components[c] sense = all_senses[c] ctname = cpx_ctnames[c] if cpx_ctnames else None if linear_nb_non_zeros > 0: indices, coefs = linear_component.unpack() # linexpr = mdl._aggregator._scal_prod((cpx_var_index_to_docplex[idx] for idx in indices), coefs) linexpr = make_terms_fn(lfactory, cpx_var_index_to_docplex, indices, coefs) else: linexpr = None if quadratic_nb_non_zeros > 0: qfactory = mdl._qfactory ind1, ind2, coefs = quadratic_component.unpack() quads = qfactory.term_dict_type() for idx1, idx2, coef in zip(ind1, ind2, coefs): quads[VarPair(cpx_var_index_to_docplex[idx1], cpx_var_index_to_docplex[idx2])] = coef else: # pragma: no cover # should not happen, but who knows quads = None quad_expr = mdl._aggregator._quad_factory.new_quad(quads=quads, linexpr=linexpr, safe=True) op = ComparisonType.cplex_ctsense_to_python_op(sense) ct = op(quad_expr, rhs) mdl.add_constraint(ct, ctname) # 4. upload indicators cpx_indicators = cpx.indicator_constraints nb_indicators = cpx_indicators.get_num() if nb_indicators: all_ind_names = [] if ignore_names else cls._safe_call_get_names(cpx_adapter, cpx_indicators.get_names) all_ind_bvars = cpx_indicators.get_indicator_variables() all_ind_rhs = cpx_indicators.get_rhs() all_ind_linearcts = cpx_indicators.get_linear_components() all_ind_senses = cpx_indicators.get_senses() all_ind_complemented = cpx_indicators.get_complemented() all_ind_types = cpx_indicators.get_types() ind_equiv_type = 3 for i in range(nb_indicators): ind_bvar = all_ind_bvars[i] ind_name = all_ind_names[i] if all_ind_names else None ind_rhs = all_ind_rhs[i] ind_linear = all_ind_linearcts[i] # SparsePair(ind, val) ind_sense = cls.parse_sense(all_ind_senses[i]) ind_complemented = all_ind_complemented[i] ind_type = all_ind_types[i] # 1 . check the bvar is ok ind_bvar = cpx_var_index_to_docplex[ind_bvar] # each var appears once ind_linexpr = cls._build_linear_expr_from_sparse_pair(lfactory, cpx_var_index_to_docplex, ind_linear) ind_lct = lfactory._new_binary_constraint(ind_linexpr, ind_sense, ind_rhs) if ind_type == ind_equiv_type: logct = lfactory.new_equivalence_constraint( ind_bvar, ind_lct, true_value=1 - ind_complemented, name=ind_name) else: logct = lfactory.new_indicator_constraint( ind_bvar, ind_lct, true_value=1 - ind_complemented, name=ind_name) mdl.add(logct) # 5. upload Piecewise linear constraints try: cpx_pwl = cpx.pwl_constraints cpx_pwl_defs = cpx_pwl.get_definitions() pwl_fallback_names = [""] * cpx_pwl.get_num() cpx_pwl_names = pwl_fallback_names if ignore_names else cls._safe_call_get_names(cpx_adapter, cpx_pwl.get_names, pwl_fallback_names) for (vary_idx, varx_idx, preslope, postslope, breakx, breaky), pwl_name in zip(cpx_pwl_defs, cpx_pwl_names): varx = cpx_var_index_to_docplex.get(varx_idx, None) vary = cpx_var_index_to_docplex.get(vary_idx, None) breakxy = [(brkx, brky) for brkx, brky in zip(breakx, breaky)] pwl_func = mdl.piecewise(preslope, breakxy, postslope, name=pwl_name) pwl_expr = mdl._lfactory.new_pwl_expr(pwl_func, varx, 0, resolve=False) pwl_expr._f_var = vary pwl_expr._ensure_resolved() except AttributeError: # pragma: no cover pass # Do not check for PWLs if Cplex version does not support them # 6. upload objective # noinspection PyPep8 try: cpx_multiobj = cpx.multiobj except AttributeError: # pragma: no cover # pre-12.9 version cpx_multiobj = None if cpx_multiobj is None or cpx_multiobj.get_num() <= 1: cpx_obj = cpx.objective cpx_sense = cpx_obj.get_sense() fast_getobj = cpx_adapter.fast_getobj if fast_getobj: with fast_getobj(cpx_env_e, cpx_lp, 0, cpx_nb_vars-1) as var_coefs_tuple: obj_expr = make_terms_seq_fn(lfactory, cpx_var_index_to_docplex, var_coefs_tuple) else: cpx_all_lin_obj_coeffs = cpx_obj.get_linear() obj_expr = compute_full_dot(mdl, cpx_all_lin_obj_coeffs) if cpx_obj.get_num_quadratic_variables() > 0: cpx_all_quad_cols_coeffs = cpx_obj.get_quadratic() quads = qfactory.term_dict_type() for v, col_coefs in zip(cpx_var_index_to_docplex, cpx_all_quad_cols_coeffs): var1 = cpx_var_index_to_docplex[v] indices, coefs = col_coefs.unpack() for idx, coef in zip(indices, coefs): vp = VarPair(var1, cpx_var_index_to_docplex[idx]) quads[vp] = quads.get(vp, 0) + coef / 2 obj_expr += qfactory.new_quad(quads=quads, linexpr=None) obj_expr += cpx.objective.get_offset() is_maximize = cpx_sense == cpx_adapter.cplex_module._internal._subinterfaces.ObjSense.maximize if is_maximize: mdl.maximize(obj_expr) else: mdl.minimize(obj_expr) else: # we have multiple objective nb_multiobjs = cpx_multiobj.get_num() exprs = [0] * nb_multiobjs priorities = [1] * nb_multiobjs weights = [1] * nb_multiobjs abstols = [0] * nb_multiobjs reltols = [0] * nb_multiobjs if ignore_names: names = ["Goal_{0}".format(g) for g in range(1, nb_multiobjs + 1)] else: names = cpx_multiobj.get_names() fast_multiobj = cpx_adapter.fast_multiobj_getobj is not None if fast_multiobj: def get_kth_multiobj(k): weight = cpx_adapter.fast_multiobj_getweight(cpx_env_e, cpx_lp, k) offset = cpx_adapter.fast_multiobj_getoffset(cpx_env_e, cpx_lp, k) priority = cpx_adapter.fast_multiobj_getprio(cpx_env_e, cpx_lp, k) abstol = cpx_adapter.fast_multiobj_getabstol(cpx_env_e, cpx_lp, k) reltol = cpx_adapter.fast_multiobj_getreltol(cpx_env_e, cpx_lp, k) with cpx_adapter.fast_multiobj_getobj(cpx_env_e, cpx_lp, k, 0, cpx_nb_vars-1) as objk_tuples: obj_expr = make_terms_seq_fn(lfactory, cpx_var_index_to_docplex, objk_tuples, constant=offset) return obj_expr, weight, priority, abstol, reltol else: def get_kth_multiobj(k): (obj_coeffs, obj_offset, weight, prio, abstol, reltol) = cpx_multiobj.get_definition(k) obj_expr = compute_full_dot(mdl, obj_coeffs, obj_offset) return obj_expr, weight, prio, abstol, reltol for m in range(nb_multiobjs): (obj_expr, weight, prio, abstol, reltol) = get_kth_multiobj(m) exprs[m] = obj_expr priorities[m] = prio weights[m] = weight abstols[m] = abstol reltols[m] = reltol sense = cpx_multiobj.get_sense() mdl.set_multi_objective(sense, exprs, priorities, weights, abstols, reltols, names) # upload sos cpx_sos = cpx.SOS cpx_sos_num = cpx_sos.get_num() if cpx_sos_num > 0: cpx_sos_types = cpx_sos.get_types() cpx_sos_indices = cpx_sos.get_sets() cpx_sos_names = cpx_sos.get_names() if not cpx_sos_names: cpx_sos_names = [None] * cpx_sos_num for sostype, sos_sparse, sos_name in zip(cpx_sos_types, cpx_sos_indices, cpx_sos_names): sos_var_indices = sos_sparse.ind sos_weights = sos_sparse.val isostype = int(sostype) sos_vars = [cpx_var_index_to_docplex[var_ix] for var_ix in sos_var_indices] mdl.add_sos(dvars=sos_vars, sos_arg=isostype, name=sos_name, weights=sos_weights) # upload lazy constraints cpx_linear_advanced = cpx.linear_constraints.advanced cpx_lazyct_num = cpx_linear_advanced.get_num_lazy_constraints() if cpx_lazyct_num: print("WARNING: found {0} lazy constraints that cannot be uploaded to DOcplex".format(cpx_lazyct_num)) mdl.output_level = final_output_level if final_checker: # need to restore checker mdl.set_checker(final_checker) except cpx_adapter.CplexError as cpx_e: # pragma: no cover print("* CPLEX error: {0!s} reading file {1}".format(cpx_e, filename)) mdl = None if debug_read: raise except ModelReaderError as mre: # pragma: no cover print("! Model reader error: {0!s} while reading file {1}".format(mre, filename)) mdl = None if debug_read: raise except DOcplexException as doe: # pragma: no cover print("! Internal DOcplex error: {0!s} while reading file {1}".format(doe, filename)) mdl = None if debug_read: raise # except Exception as any_e: # pragma: no cover # print("Internal exception raised: {0} msg={1!s} while reading file '{2}'".format(type(any_e), any_e, filename)) # mdl = None # if debug_read: # raise finally: # clean up CPLEX instance... # cpx.end() pass if mdl: # reset engine, if necessary if final_agent == 'zero': pass # nothing to do if final_agent == 'cplex': mdl._set_engine(CplexEngine(mdl, _cplex=cpx_adapter)) # mdl._check_scope_indices() else: # set a new non-cplex agent mdl._set_new_engine_from_agent(final_agent) mdl._set_solver_agent(final_agent) return mdl
[docs] @classmethod def read_model(cls, filename, model_name=None, verbose=False, model_class=None, **kwargs): """ This method is a synonym of `read` for compatibility. """ import warnings warnings.warn("ModelReader.read_model is deprecated, use class method ModelReader.read()", DeprecationWarning) return cls.read(filename, model_name, verbose, model_class, **kwargs)
[docs]def read_model(filename, model_name=None, verbose=False, **kwargs): """ Reads a model from a CPLEX export file. Accepts all formats exported by CPLEX: LP, SAV, SAV.gz, MPS. If an error occurs while reading the file, the message of the exception is printed and the function returns None. Args: filename: The model file to read. model_name: An optional name for the newly created model. If None, the model name will be the path basename. verbose: An optional flag to print informative messages, default is False. kwargs: A dict of keyword-based arguments that are passed to the model contructor. Note: This function requires CPLEX runtime, otherwise an exceotion is raised. Example: `m = read_model("c:/temp/foo.mps", model_name="docplex_foo", solver_agent="local", output_level=100)` Returns: An instance of Model, or None if an exception is raised. See Also: :class:`docplex.mp.model.Model` """ return ModelReader.read(filename, model_name=model_name, verbose=verbose, **kwargs)