コード例 #1
0
 def _get_first_fraction_solution_pivot(self):
     sol = self.orig_problem_solution
     int_test = float_comp(sol - np.round(sol), 0.0, equal=True)
     if np.all(int_test):
         return None
     else:
         col_idx = np.where(
             np.logical_not(int_test).flat)[0][0]  # first fraction
         # base_columns = SimplexSolver._get_base_columns_indx(self._tableau)
         # row_idx = np.where(float_comp(self._tableau.A[:, base_columns[col_idx]], 1.0, equal=True).flat)[0][0]
         row_idx = np.where(
             float_comp(self._tableau.A[:, col_idx], 1.0,
                        equal=True).flat)[0][0]
         # return pivot location for canonical fraction solution constraint
         return row_idx, col_idx
コード例 #2
0
 def _choose_pivot_primal(tableau):
     j = 0
     while j < tableau.ct.shape[1] and \
             float_comp(tableau.ct[0, j], 0.0, greater=True, equal=True):
         j += 1
     if j < tableau.ct.shape[1]:
         posit = np.where(
             float_comp(tableau.A[:, j].flat, 0.0, greater=True))
         posit = posit[0]
         if posit.size == 0:  # unbounded
             return None, j  # return the last chosen column
         else:
             i = posit[np.argmin(tableau.b[posit, 0] / tableau.A[posit, j])]
             return i, j
     else:
         return None  # No element in (-c)^t negative
コード例 #3
0
 def _choose_pivot_dual(tableau):
     i = 0
     while i < tableau.b.shape[0] and \
             float_comp(tableau.b[i, 0], 0.0, greater=True, equal=True):
         i += 1
     if i < tableau.b.shape[0]:
         negat = np.where(float_comp(tableau.A[i, :].flat, 0.0, less=True))
         negat = negat[0]
         if negat.size == 0:  # infeasible
             return i, None
         else:
             j = negat[np.argmin(tableau.ct[0, negat] /
                                 (-1 * tableau.A[i, negat]))]
             return i, j
     else:
         return None  # No element in b negative
コード例 #4
0
 def _get_fraction_solution_idx(self):
     sol = self.orig_problem_solution
     int_test = float_comp(sol - np.round(sol), 0.0, equal=True)
     if np.all(int_test):
         return None
     else:
         return np.where(
             np.logical_not(int_test).flat)[0][0]  # first fraction solution
コード例 #5
0
def is_pivot_column(columns):
    columns = np.asarray(columns, np.float64)
    ret = np.empty(columns.shape[1], np.bool)
    for j in np.arange(0, columns.shape[1]):
        line_equal_one = np.isclose(columns[:, j], [1.0])
        # only one line with 1.0
        ret[j] = line_equal_one.sum() == 1
        # all other lines with 0.0
        ret[j] = ret[j] and np.all(
            float_comp(
                columns[np.logical_not(line_equal_one), j], 0.0, equal=True))
    return ret
コード例 #6
0
    def run_simplex(self, fout=None):
        # need auxiliary tableau?
        if np.any(float_comp(self._tableau.ct, 0.0, less=True)) and \
                np.any(float_comp(self._tableau.b, 0.0, less=True)):
            aux_tableau = self._build_aux_tableau()
            num_cons = aux_tableau.A.shape[0]
            base_columns = np.arange(-num_cons, 0)
            SimplexSolver._update_ct_to_canonical_form(aux_tableau,
                                                       base_columns, fout)
            self._run_simplex(aux_tableau, fout)
            if np.all(float_comp(aux_tableau.obj, 0.0,
                                 equal=False)):  # Infeasible LP
                self.lp_type = "infeasible"
                self._certificate = aux_tableau.yt.T
                return
            else:
                num_cons = aux_tableau.A.shape[0]
                # updating the original tableau with the contents of the aux tableau
                self._tableau.mat[1:, :] = np.hstack(
                    (aux_tableau.mat[1:, :-(num_cons + 1)], aux_tableau.b))
                bcols = SimplexSolver._get_base_columns_indx(aux_tableau)
                SimplexSolver._update_ct_to_canonical_form(
                    self._tableau, bcols, fout)

        last_pivot = self._run_simplex(self._tableau, fout)
        if last_pivot is None:  # Bounded LP
            self.lp_type = "bounded"
            self._certificate = self._tableau.yt.T
        else:  # Unbounded  or Infeasible LP
            if last_pivot[0] is not None:  # Infeasible LP
                self.lp_type = "infeasible"
                self._certificate = self._tableau.op[last_pivot[0], :].T
            elif last_pivot[1] is not None:  # Unbounded LP
                self.lp_type = "unbounded"
                self._certificate = self._calc_unbounded_certificate(
                    last_pivot[1])
            else:
                raise Exception("Result from simplex not expected")
コード例 #7
0
    def _run_solver_recursive(self, best_solution, fout=None):
        super().run_simplex(fout)
        if self.lp_type == "bounded":
            fract_sol_idx = self._get_fraction_solution_idx()
            if fract_sol_idx is None:
                if best_solution is None or self.objvalue > best_solution.obj[
                        0, 0]:
                    return self._tableau
            else:
                if best_solution is None or self.objvalue > best_solution.obj[
                        0, 0]:  # if not prunning
                    orig_tableau = self._tableau
                    orig_certificate = self._certificate

                    sol = self.orig_problem_solution
                    row_pivot = np.where(
                        float_comp(self._tableau.A[:, fract_sol_idx],
                                   1.0,
                                   equal=True).flat)[0][0]
                    new_cons = np.zeros((1, orig_tableau.num_vars + 2),
                                        np.float64)
                    new_cons[0, -2] = 1.0

                    new_cons[0, fract_sol_idx] = 1.0
                    new_cons[0, -1] = np.floor(sol[fract_sol_idx])
                    new_tableau_less = deepcopy(orig_tableau)
                    new_tableau_less.add_constraint(new_cons)
                    new_tableau_less.mat = gausselim.pivoting(
                        new_tableau_less.mat, row_pivot + 1,
                        fract_sol_idx + new_tableau_less.op.shape[1])
                    self._tableau = new_tableau_less
                    best_solution = self._run_solver_recursive(
                        best_solution, fout)

                    new_cons[0, fract_sol_idx] = -1.0
                    new_cons[0, -1] = -np.ceil(sol[fract_sol_idx])
                    new_tableau_greater = deepcopy(orig_tableau)
                    new_tableau_greater.add_constraint(new_cons)
                    new_tableau_greater.mat = gausselim.pivoting(
                        new_tableau_greater.mat, row_pivot + 1,
                        fract_sol_idx + new_tableau_greater.op.shape[1])
                    self._tableau = new_tableau_greater
                    best_solution = self._run_solver_recursive(
                        best_solution, fout)

                    self._tableau = orig_tableau
                    self._certificate = orig_certificate

        return best_solution
コード例 #8
0
    def _build_aux_tableau(self):
        num_cons = self._tableau.A.shape[0]
        aux_c = np.zeros_like(self._tableau.ct)
        aux_c = np.asmatrix(
            np.hstack((np.zeros((1, num_cons)), aux_c, np.ones(
                (1, num_cons)))), np.float64)
        b_neglines = np.where(float_comp(self._tableau.b, 0.0, less=True))[0]
        opmat = np.asmatrix(np.identity(num_cons), np.float64)
        aux_opA = np.hstack((opmat, self._tableau.A))
        aux_opA[b_neglines, :] = aux_opA[b_neglines, :] * (-1)
        aux_opA = np.hstack((aux_opA, np.identity(aux_opA.shape[0])))
        aux_b = np.copy(self._tableau.b)
        aux_b[b_neglines, :] = aux_b[b_neglines, :] * (-1)

        aux_tab_mat = np.vstack((np.hstack(
            (aux_c, [[0.0]])), np.hstack((aux_opA, aux_b))))

        aux_tab = Tableau(aux_tab_mat)

        return aux_tab
コード例 #9
0
 def _get_base_columns_indx(tableau):
     base_columns = np.where(float_comp(tableau.ct, 0.0, equal=True))[1]
     base_columns = base_columns[gausselim.is_pivot_column(
         tableau.A[:, base_columns])]
     return base_columns
コード例 #10
0
 def _choose_pivot(tableau):
     if np.alltrue(float_comp(tableau.ct, 0.0, greater=True, equal=True)):
         return SimplexSolver._choose_pivot_dual(tableau)
     if np.alltrue(float_comp(tableau.b, 0.0, greater=True, equal=True)):
         return SimplexSolver._choose_pivot_primal(tableau)