def _process_rhs(self, data_line: DataLine): if len(self._rhs) != len(self.constraint_names): self._rhs = np.zeros(len(self.constraint_names)) self._add_rhs(data_line.second_name(), data_line.first_number()) if data_line.has_third_name() and data_line.has_second_number(): self._add_rhs(data_line.third_name(), data_line.second_number())
def test_first_number_column(line, expected): """ The first numeric field is the 25-36 column range (inclusive). """ padding = " " * 24 # starts at column 25, so 24 spaces. data_line = DataLine(padding + line) assert_almost_equal(data_line.first_number(), expected)
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 test_first_data_entry(): """ Tests if the DataLine class correctly parses the first data entry. """ # From the sslp_5_25_50.cor file. line = " x_1 c2 188" data_line = DataLine(line) assert_equal(data_line.first_name(), "x_1") assert_equal(data_line.second_name(), "c2") assert_almost_equal(data_line.first_number(), 188)
def _parse_column(self, data_line: DataLine): var = data_line.first_name() if var not in self._var2idx: self._variable_names.append(var) self._types.append('I' if self._parse_ints else 'C') self._var2idx[var] = len(self._variable_names) - 1 constr = data_line.second_name() value = data_line.first_number() self._add_value(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._add_value(constr, var, value)
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'