N
N
Ntonk2021-04-15 22:39:11
Python
Ntonk, 2021-04-15 22:39:11

Why is the modified simplex method looping (Python implementation with numpy)?

I'm trying to implement a modified simplex method in multiplicative form in Python using numpy. I constantly face the problem that it works for me only for maximization, and on small matrices - it calculates large ones with errors, the values ​​of the objective function are very different from what they should be. On minimization most often goes in cycles. The theory is stated, for example, here . Here is an example of my minify code:

class Simplex(object):
    def __init__(self, A: np.ndarray, b: np.ndarray, c: np.ndarray):
        base_size = A.shape[0]  # Кол-во базисных векторов
        I = np.eye(base_size)  # Единичная матрица - начальный базис системы. 
        self.extended_matrix = np.concatenate((A, I), axis=1)  # Расширенная матрица системы
        self.free_size = A.shape[1]  # Кол-во свободных векторов
        self.b = b  # Правые части ограничений
        self.base_inv = I  # Начальная обратная матрица базиса равна его прямой матрице, т.к. является единичной
        self.c = np.concatenate((c, np.zeros(base_size)))  # Коэффициенты целевой ф-ции с учетом базисных переменных
        self.c_i = [i for i, coeff in enumerate(self.c)]  # Индексы всех переменных
        
    @property
    def c_f_indices(self):
        """
        Индексы свободных переменных. 
        """
        return self.c_i[:self.free_size]
    
    @property
    def c_T_B(self):
        """
        Коэффициенты целевой функции при базисных переменных.
        """
        c_B_indices = self.c_i[self.free_size:]  # Индексы базисных переменных.
        return self.c[c_B_indices]
    
    @property
    def c_T_f(self):
        """
        Коэффициенты целевой функции при свободных переменных.
        """
        return self.c[self.c_f_indices]
        
    @property
    def free(self):
        """
        Свободные векторы.
        """
        return self.extended_matrix[:, self.c_f_indices]
    
    @property
    def y_T(self):
        """
        Вектор относительных оценок (разрешающие множители по Канторовичу).
        """
        return self.c_T_B @ self.base_inv
    
    @property
    def deltas(self):
        """
        Текущие оценки векторов.
        """
        return (self.y_T @ self.free) - self.c_T_f 
    


    def _swap(self, exits: int, enters: int) -> None:
        """
        Включение/исключение в/из базис(-а) соответствующих векторов
        """
        self.c_i[enters], self.c_i[exits + self.free_size] = self.c_i[exits + self.free_size], self.c_i[enters]
    
    def optimize(self):
        while any([delta > 0 for delta in self.deltas]): # В случае максимизации будет < 0
            x_B = self.base_inv @ self.b  # Текущие значения базисных переменных
            enters_base = np.argmax(self.deltas)  # Нахождение вектора, включаемого в базис. В случае максимизации будет argmin
            
            # Нахождение вектора, исключаемого из базиса:
            alpha = self.base_inv @ self.free[:, enters_base]

            try:
                exits_base = np.argmin([b/a if a > 0 else np.inf for b, a in zip(x_B, alpha)])
                assert alpha[exits_base] != 0
            except (ValueError, AssertionError):
                raise Exception("No solutions")
            
            # Нахождение матрицы соотношения E_r и вычисление новой обратной матрицы базиса системы:
            zetas = [-alpha[j] / alpha[exits_base] if j != exits_base else 1/alpha[exits_base] for j, a_j in enumerate(alpha)]
            E = np.eye(self.free.shape[0])
            E[:, exits_base] = zetas
            self.base_inv = E @ self.base_inv
            
            # Включение/исключение в/из базис(-а) соответствующих векторов:
            self._swap(exits_base, enters_base)
            
        return self.c_T_B @ self.base_inv @ self.b # Итоговое значение целевой функции


I tried, among other things, to sort the indices of free variables, but I still ended up looping. And, by the way, I found someone's similar implementation , which also makes gross errors on large matrices. Two weeks of breaking the head did not lead to anything. Where might the error be? Thank you in advance.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question