def test_indicator_and_name(): """ Tests if the indicator and name are correctly parsed. """ data_line = DataLine(" N OBJ") # from the LandS.cor file. assert_equal(data_line.indicator(), "N") assert_equal(data_line.first_name(), "OBJ")
def _process_scenarios(self, data_line: DataLine): if data_line.indicator() == "SC": # new scenario scen = Scenario(data_line.first_name(), data_line.second_name(), data_line.third_name(), data_line.first_number()) self._current_scen = scen return var = data_line.first_name() constr = data_line.second_name() value = data_line.first_number() assert self._current_scen is not None self._current_scen.add_modification(constr, var, value) if data_line.has_third_name() and data_line.has_second_number(): constr = data_line.third_name() value = data_line.second_number() self._current_scen.add_modification(constr, var, value)
def _process_rows(self, data_line: DataLine): indicator = data_line.indicator() name = data_line.first_name() assert indicator in _CONSTRAINT_SENSES # This is a "no restriction" row, which indicates an objective function. # There can be more than one such row, but there can only be one # objective. We take the first such row as the objective, and then # ignore any subsequent "no restriction" rows. if indicator == 'N': if self.objective_name == "": logger.debug(f"Setting {name} as objective.") self._objective_name = name return else: self._constr_names.append(name) self._senses.append(indicator) self._constr2idx[name] = len(self._constr_names) - 1
def _process_bounds(self, data_line: DataLine): """ There are a ton of bound types, but the most common are listed below, originally due to http://lpsolve.sourceforge.net/5.5/mps-format.htm. A bound is specified by a two-letter type and a value b. - LO lower bound b <= x (< +inf) - UP upper bound (0 <=) x <= b - FX fixed variable x = b - FR free variable -inf < x < +inf - MI lower bound -inf -inf < x (<= 0) - PL upper bound +inf (0 <=) x < +inf - BV binary variable x = 0 or 1 - LI integer variable b <= x (< +inf) - UI integer variable (0 <=) x <= b Raises ------ ValueError When the bound type is not understood. """ if len(self._lb) != len(self.variable_names) != len(self._ub): self._lb = np.zeros(len(self.variable_names)) self._ub = np.full(len(self.variable_names), np.inf) bound_type = data_line.indicator() if bound_type not in _BOUNDS_TYPES: msg = f"Bounds of type {bound_type} are not understood." logger.error(msg) raise ValueError(msg) var = data_line.second_name() idx = self._var2idx[var] # The value is clear from the type, and need not have been specified. # Hence we treat these separately, and then return. if bound_type in {"FR", "MI", "PL", "BV"}: if bound_type == "FR": # free variable self._lb[idx] = -np.inf self._ub[idx] = np.inf if bound_type == "MI": # -inf lower bound self._lb[idx] = -np.inf if bound_type == "PL": # +inf upper bound self._ub[idx] = np.inf if bound_type == "BV": # binary variable self._lb[idx] = 0 self._ub[idx] = 1 self._types[idx] = 'B' return value = data_line.first_number() if bound_type == "LO": # lower bound self._lb[idx] = value if bound_type == "UP": # upper bound self._ub[idx] = value if bound_type == "FX": # fixed variable self._lb[idx] = value self._ub[idx] = value if bound_type == "LI": # integer variable, lower bound self._lb[idx] = value self._types[idx] = 'I' if bound_type == "UI": # integer variable, upper bound self._ub[idx] = value self._types[idx] = 'I'
def test_indicator_columns(line, expected): """ The indicator field is the 2-3 column range (inclusive). """ data_line = DataLine(line) assert_equal(data_line.indicator(), expected)