├── .gitignore ├── README.md ├── requirements.txt ├── task1.py ├── task2.py ├── task3.py ├── task4.py ├── task5.py └── task6.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # vscode 132 | .vscode 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Optimization-and-Control-Methods 2 | 3 | 4 | ## Problem 1. Формула Шермана-Моррисона 5 | ### Input file name: standard input 6 | ### Output file name: standard output 7 | ### Time limit: 5 s 8 | ### Memory limit: 256 MB 9 | 10 | ``` 11 | Вам дана квадратная матрица A и ее обратная матрица B. 12 | Вам необходимо заменить в матрице A i-й столбец на вектор x и найти обратную матрицу к новой матрице. 13 | Гарантируется что матрица B является обратной матрицей к матрице A. 14 | ``` 15 | 16 | ### Input 17 | ``` 18 | В первой строке входных данных находится два целых числа n, i (1<=n<=500, 1<=i<=n) — размер квадратной матрицы, а также номер столбца который необходимо заменить пронумерованный с единицы. 19 | В следующих n строках задано по n дробных чисел a[i][j] (−500<=a[i][j]<=500) — значения элементов матрицы A. 20 | В следующих n строках задано по n дробных чисел b[i][j] (−500<=b[i][j]<=500) — значения элементов матрицы B. 21 | В следующей строке задано по n чисел x[i]​ (−500<=x[i]<=500) — значения элементов вектора x. 22 | ``` 23 | 24 | ### Output 25 | ``` 26 | В первой строке выведите YES, если новая матрица является невырожденной, NO — в противном случае. Если новая матрица является невырожденной выведите n строк по n чисел в каждой — новую обратную матрицу. 27 | Абсолютная или относительная погрешность не должны превышать 10^-6. 28 | ``` 29 | 30 | 31 | ## Problem 2. Основная фаза симплекс-метода 32 | ### Input file name: standard input 33 | ### Output file name: standard output 34 | ### Time limit: 3 s 35 | ### Memory limit: 256 MB 36 | 37 | ``` 38 | В данной задаче необходимо реализовать алгоритм основной фазы симплекс метода. 39 | В задаче дана матрица A, вектор b, а также вектор c. 40 | А также вам известен начальный базисный план и базис Jб​. 41 | Необходимо вывести оптимальный план для заданных соотношений: 42 | Ax=b 43 | cx→max⁡ 44 | 45 | ``` 46 | 47 | 48 | 49 | ### Input 50 | 51 | ``` 52 | В первой строке входных данных находится два целых числа m, n (1<=m<=n<=500 ) — размер матрицы A, mстрок по n столбцов. 53 | В следующих m строках задано по n целых чисел a[i][j] (−500<=a[i][j]<=500) — значения элементов матрицы A. 54 | В следующей строке задано m целых чисел b[i] (−500<=b[i]<=500) — значения элементов вектора b. 55 | В следующей строке задано n целых чисел c[i]​ (−500<=c[i]<=500) — значения элементов вектора c. 56 | В следующей строке задано n дробных чисел x[i] (−500<=x[i]<=500) — значения элементов начального плана x. 57 | В следующей строке задано m целых чисел j[i] ​(−500<=j[i]<=500) — значения индексов базиса. 58 | ``` 59 | 60 | ### Output 61 | 62 | ``` 63 | В первой строке выходных данных необходимо вывести следующее: 64 | Если задача не ограничена выведите Unbounded 65 | Иначе выведите Bounded 66 | На второй строке выходных данных, в случае если ответ существует, необходимо вывести n дробных чисел через пробел — значения вектора x. 67 | Абсолютная или относительная погрешность не должны превышать 10^(-6). 68 | ``` 69 | 70 | 71 | 72 | ## Problem 3. Первая фаза симплекс метода 73 | ### Input file name: standard input 74 | ### Output file name: standard output 75 | ### Time limit: 3 s 76 | ### Memory limit: 256 MB 77 | 78 | ``` 79 | В данной задаче необходимо реализовать алгоритм первой фазы симплекс метода. 80 | В задаче дана матрица A, вектор b, а также вектор c. 81 | Необходимо вывести любой план для заданных соотношений 82 | Ax=b 83 | cx→max⁡ 84 | ``` 85 | 86 | ### Input 87 | 88 | ``` 89 | В первой строке входных данных находится два целых числа m, n (1<=m<=n<=500) — размер матрицы A, m строк по n столбцов. 90 | В следующих m строках задано по n целых чисел a[i][j] (−500<=a[i][j]≤500) — значения элементов матрицы A. 91 | В следующей строке задано m целых чисел b[i]​ (−500<=b[i]<=500) — значения элементов вектора b. 92 | В следующей строке задано n целых чисел c[i] (−500<=c[i]<=500) — значения элементов вектора c. 93 | ``` 94 | 95 | ### Output 96 | 97 | ``` 98 | В первой строке выходных данных необходимо вывести следующее: 99 | Если данная задача не имеет решений необходимо вывести No solution. 100 | Если задача не ограничена выведите Unbounded 101 | Иначе выведите Bounded 102 | На второй строке выходных данных, в случае если ответ существует, необходимо вывести n дробных чисел через пробел — значения вектора x. 103 | Абсолютная или относительная погрешность не должны превышать 10^(-16). 104 | ``` 105 | 106 | 107 | 108 | 109 | ## Problem 4. Симплекс метод 110 | ### Input file name: standard input 111 | ### Output file name: standard output 112 | ### Time limit: 3 s 113 | ### Memory limit: 256 MB 114 | 115 | ``` 116 | В данной задаче необходимо реализовать алгоритм симплекс метода. 117 | В задаче дана матрица A, вектор b, а также вектор c. 118 | Необходимо вывести оптимальный план для заданных соотношений 119 | Ax=b 120 | cx→max⁡ 121 | ``` 122 | 123 | ### Input 124 | 125 | ``` 126 | В первой строке входных данных находится два целых числа m, n (1<=m<=n<=500) — размер матрицы A, m строк по n столбцов. 127 | В следующих m строках задано по n целых чисел a[i][j] (−500<=a[i][j]≤500) — значения элементов матрицы A. 128 | В следующей строке задано m целых чисел b[i]​ (−500<=b[i]<=500) — значения элементов вектора b. 129 | В следующей строке задано n целых чисел c[i] (−500<=c[i]<=500) — значения элементов вектора c. 130 | ``` 131 | 132 | ### Output 133 | 134 | ``` 135 | В первой строке выходных данных необходимо вывести следующее: 136 | Если данная задача не имеет решений необходимо вывести No solution. 137 | Если задача не ограничена выведите Unbounded 138 | Иначе выведите Bounded 139 | На второй строке выходных данных, в случае если ответ существует, необходимо вывести n дробных чисел через пробел — значения вектора x. 140 | Абсолютная или относительная погрешность не должны превышать 10^(-16). 141 | ``` 142 | 143 | 144 | ## Problem 5. Матричная транспортная задача 145 | ### Input file name: standard input 146 | ### Output file name: standard output 147 | ### Time limit: 3 s 148 | ### Memory limit: 256 MB 149 | 150 | ``` 151 | Пусть имеется mmm пунктов производства некоторого однородного продукта и nnn пунктов его потребления. Для каждого пункта производства i=1,2,…,m и для каждого пункта потребления j=1,2,…,n заданы следующие величины: объём производства a[i] пункте производства i, объём потребления b[j]​ в пункте потребления j, затраты на перевозку единицы продукта c[i][j]​ от пункта производства i до пункта потребления j. 152 | Требуется составить план перевозок, позволяющий вывезти продукты производителей, обеспечивающий потребности потребителей и дающий минимум суммарных затрат на перевозку. 153 | Обозначим как x[i][j] объёмы перевозок от поставщика i до потребителя j. 154 | ``` 155 | 156 | ### Input 157 | 158 | ``` 159 | В первой строке входных данных находится два целых числа m, n (1<=m<=n<=200) — количество пунктов производства и пунктов потребления соответственно. 160 | В следующих m строках задано по n целых чисел c[i][j]​ (−500<=c[i][j]<=500) — значения элементов стоимости перевозок. 161 | В следующей строке задано m целых чисел a[i] (0<=a[i]<=500) — значения элементов вектора a. 162 | В следующей строке задано n целых чисел b[i] (0<=b[i]<=500) — значения элементов вектора b. 163 | ``` 164 | 165 | ### Output 166 | 167 | ``` 168 | Выведите m строк по n целых чисел — объемы перевозок. 169 | ``` 170 | 171 | 172 | 173 | 174 | ## Problem 6. Квадратичное программирование 175 | ### Input file name: standard input 176 | ### Output file name: standard output 177 | ### Time limit: 3 s 178 | ### Memory limit: 256 MB 179 | 180 | ``` 181 | В данной задаче необходимо реализовать итерационный алгоритм для решения задачи квадратичного программирования. 182 | В задаче дана матрица A, вектор b, вектор c и симметричная положительно полуопределенная матрица D. Также вам известен опорный план {x, J[опт], J*}. 183 | 184 | 185 | Необходимо вывести оптимальный план для заданных соотношений: 186 | Ax = b, x >= 0 187 | c'x + (1/2)x'Dx -> min 188 | ``` 189 | 190 | 191 | ### Input 192 | 193 | ``` 194 | В первой строке входных данных находится два целых числа m, n, k (1<=m<=k<=n<=100) — размер матрицы A, m строк по n столбцов, а также k - количество индексов расширенного базиса. 195 | В следующих m строках задано по n целых чисел a[i][j] (−500<=a[i][j]<=500) — значения элементов матрицы A. 196 | В следующей строке задано m целых чисел b[i]​ (−500<=b[i]<=500) — значения элементов вектора b. 197 | В следующей строке задано n целых чисел c[i]​ (−500<=c[i]<=500) — значения элементов вектора c. 198 | В следующих n строках задано по n целых чисел d[i][j]​ (−500<=d[i][j]<=500) — значения элементов матрицы D. 199 | В следующей строке задано n дробных чисел x[i] (0<=x[i]<=500) — значения элементов плана x. 200 | В следующей строке задано m целых чисел j[опт][i]​​ (1<=j[опт][i]<=n) — значения индексов опорного базиса. 201 | В следующей строке задано k целых чисел j*[i] (1<=j*[i]<=n) — значения индексов расширенного базиса. 202 | ``` 203 | 204 | ### Output 205 | 206 | ``` 207 | В первой строке выходных данных необходимо вывести следующее: 208 | Если задача не ограничена выведите Unbounded 209 | Иначе выведите Bounded 210 | На второй строке выходных данных, в случае если ответ существует, необходимо вывести n дробных чисел через пробел — значения вектора x. 211 | Абсолютная или относительная погрешность не должны превышать 10^(-6). 212 | ``` -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.18.3 2 | -------------------------------------------------------------------------------- /task1.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def input_matrix(n): 5 | matrix = [] 6 | for el in range(n): 7 | matrix.append(list(map(float, input().split()))) 8 | return matrix 9 | 10 | 11 | def input_vector(n): 12 | return list(map(float, input().split())) 13 | 14 | 15 | def mofidy_output_matrix(matrix): 16 | answer = [] 17 | for el in matrix: 18 | answer.append(' '.join(map(str, el))) 19 | return '\n'.join(answer) 20 | 21 | 22 | def sherman_morrison(): 23 | n, i = list(map(int, input().split())) 24 | 25 | matrix_a = np.array(input_matrix(n)) 26 | matrix_b = np.array(input_matrix(n)) 27 | vector_x = np.array(input_vector(n)) 28 | vector_z = matrix_b.dot(vector_x) 29 | 30 | if vector_z[i - 1] == 0: 31 | return 'NO' 32 | 33 | vector_l = vector_z.copy() 34 | vector_l[i - 1] = -1 35 | 36 | vector_l_cover = -1 / vector_z[i - 1] * vector_l 37 | 38 | matrix_m = np.eye(n) 39 | matrix_m[:, i - 1] = vector_l_cover 40 | 41 | return f'YES\n{mofidy_output_matrix(matrix_m.dot(matrix_b))}' 42 | 43 | 44 | if __name__ == '__main__': 45 | print(sherman_morrison()) 46 | -------------------------------------------------------------------------------- /task2.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def ban_linalg_inv(source_matrix): 5 | size = len(source_matrix) 6 | matrix = np.concatenate((source_matrix, np.eye(size)), axis=1) 7 | 8 | for i in range(size): 9 | j = i 10 | while matrix[j][i] == 0 and j < size: 11 | j += 1 12 | if j == size: 13 | return None 14 | if j > 0: 15 | matrix[[i, j]] = matrix[[j, i]] 16 | 17 | matrix[i] = matrix[i] / matrix[i][i] 18 | 19 | for j in range(i + 1, size): 20 | matrix[j] -= matrix[i] * matrix[j][i] * matrix[i][i] 21 | 22 | for i in range(size-1, -1, -1): 23 | for j in range(i-1, -1, -1): 24 | matrix[j] = matrix[j] - matrix[j][i] * matrix[i] 25 | 26 | return matrix[:, size:] 27 | 28 | 29 | def input_matrix(m): 30 | matrix = [] 31 | for el in range(m): 32 | matrix.append(list(map(int, input().split()))) 33 | return np.array(matrix) 34 | 35 | 36 | def input_vector(): 37 | return list(map(int, input().split())) 38 | 39 | 40 | def input_float_vector(): 41 | return list(map(float, input().split())) 42 | 43 | 44 | def create_matrix_ab(matrix_a, vector_jb): 45 | size = len(vector_jb) 46 | matrix_ab = np.zeros((size, size)) 47 | 48 | for index, el in enumerate(vector_jb): 49 | matrix_ab[:, index] = matrix_a[:, el-1] 50 | 51 | return matrix_ab 52 | 53 | 54 | def create_vector_cb(vector_c, vector_jb): 55 | vector_cb = np.zeros(len(vector_jb)) 56 | 57 | for i, el in enumerate(vector_jb): 58 | vector_cb[i] = vector_c[el-1] 59 | 60 | return vector_cb 61 | 62 | 63 | def find_min_delta(vector_delta, all_j, vector_jb): 64 | vector_jb_H = all_j - set(vector_jb) 65 | 66 | if vector_jb_H == set(): 67 | return (1, 1) 68 | 69 | min_delta = [] 70 | for i in vector_jb_H: 71 | min_delta.append(vector_delta[i-1]) 72 | 73 | delta = min(min_delta) 74 | return (min_delta.index(delta), delta) 75 | 76 | 77 | def min_theta(vector_x, vector_z, vector_jb): 78 | vector_theta = [] 79 | min_index = 0 80 | min_value = -1 81 | i = 0 82 | for z, jb in zip(vector_z, vector_jb): 83 | if z > 0: 84 | theta = vector_x[jb-1] / z 85 | vector_theta.append(theta) 86 | if theta <= min(vector_theta): 87 | min_index = i 88 | min_value = theta 89 | i += 1 90 | return (min_value, min_index+1) 91 | 92 | 93 | def create_vector_x_new(vector_x, vector_z, vector_jb, j0, theta, m): 94 | vector_x_new = np.zeros_like(vector_x) 95 | 96 | for i in range(m): 97 | index = vector_jb[i] - 1 98 | vector_x_new[index] = vector_x[index] - theta * vector_z[i] 99 | 100 | vector_x_new[j0-1] = theta 101 | 102 | return vector_x_new 103 | 104 | 105 | def main_stage_simplex_method(): 106 | m, n = list(map(int, input().split())) 107 | all_j = {i for i in range(1, n+1)} 108 | 109 | matrix_a = input_matrix(m) 110 | vector_b = input_vector() 111 | vector_c = input_vector() 112 | vector_x = input_float_vector() 113 | vector_jb = input_vector() 114 | 115 | while True: 116 | matrix_ab = create_matrix_ab(matrix_a.copy(), vector_jb.copy()) 117 | try: 118 | matrix_b = np.linalg.inv(matrix_ab.copy()) 119 | except np.linalg.LinAlgError: 120 | print('Unbounded') 121 | exit() 122 | 123 | vector_cb = create_vector_cb(vector_c.copy(), vector_jb.copy()) 124 | 125 | vector_u = vector_cb.dot(matrix_b.copy()) 126 | 127 | vector_delta = vector_u.dot(matrix_a.copy()) - vector_c 128 | 129 | j0, min_delta = find_min_delta(vector_delta, all_j, vector_jb) 130 | 131 | if min_delta >= 0: 132 | return f'Bounded\n{" ".join(map(str, vector_x))}\n' 133 | 134 | j0 = vector_delta.argmin() + 1 135 | 136 | vector_z = matrix_b.dot(matrix_a[:, j0-1]) 137 | 138 | theta, s = min_theta( 139 | vector_x.copy(), vector_z.copy(), vector_jb.copy()) 140 | 141 | if theta == -1: 142 | return 'Unbounded' 143 | 144 | js = vector_jb[s-1] 145 | 146 | vector_x = create_vector_x_new( 147 | vector_x.copy(), vector_z.copy(), vector_jb.copy(), 148 | j0, theta, m) 149 | 150 | vector_jb[vector_jb.index(js)] = j0 151 | 152 | 153 | if __name__ == '__main__': 154 | print(main_stage_simplex_method()) 155 | -------------------------------------------------------------------------------- /task3.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | 4 | 5 | def input_matrix(m): 6 | matrix = [] 7 | for el in range(m): 8 | matrix.append(list(map(int, input().split()))) 9 | return np.array(matrix) 10 | 11 | 12 | def input_vector(): 13 | return list(map(int, input().split())) 14 | 15 | 16 | def get_inverted(matrix_b, vector_x, position): 17 | vector_l = matrix_b.dot(vector_x.T) 18 | if vector_l[position] == 0: 19 | return None 20 | 21 | vector_l_cover = vector_l[position] 22 | vector_l[position] = -1 23 | vector_l *= -1 / vector_l_cover 24 | 25 | matrix_b_new = np.eye(len(matrix_b), dtype=float) 26 | matrix_b_new[:, position] = vector_l 27 | 28 | return matrix_b_new.dot(matrix_b) 29 | 30 | 31 | def main_stage_simplex_method(m, n, matrix_a, vector_b, vector_c, vector_x, vector_jb): 32 | if m == n: 33 | return vector_x 34 | matrix_ab = matrix_a[:, vector_jb] 35 | matrix_b = np.linalg.inv(matrix_ab) 36 | 37 | while True: 38 | vector_jb_n = [i for i in range(n) if i not in vector_jb] 39 | 40 | delta = vector_c[vector_jb].dot(matrix_b).dot(matrix_a[:, vector_jb_n]) - vector_c[vector_jb_n] 41 | 42 | checker = -1 43 | for i, el in enumerate(delta): 44 | if el < 0: 45 | checker = i 46 | break 47 | if checker == -1: 48 | return vector_x 49 | 50 | j0 = vector_jb_n[checker] 51 | 52 | vector_z = matrix_b.dot(matrix_a[:, j0]) 53 | if all([i <= 0 for i in vector_z]): 54 | return None 55 | 56 | theta = [vector_x[vector_jb[i]] / vector_z[i] if vector_z[i] > 0 else math.inf for i in range(m)] 57 | 58 | theta_0 = min(theta) 59 | s = theta.index(theta_0) 60 | vector_jb[s] = j0 61 | 62 | matrix_b = get_inverted(matrix_b, matrix_a[:, j0], s) 63 | 64 | if matrix_b is None: 65 | return None 66 | 67 | vector_x_new = np.zeros(n, dtype=float) 68 | vector_x_new[vector_jb] = vector_x[vector_jb] - theta_0 * vector_z 69 | vector_x_new[j0] = theta_0 70 | vector_x = vector_x_new 71 | 72 | 73 | def first_step_simplex_method(matrix_a, vector_b, m, n): 74 | for i in range(m): 75 | if vector_b[i] < 0: 76 | vector_b[i] *= -1 77 | matrix_a[i] *= -1 78 | 79 | vector_jb = [i for i in range(n, n + m)] 80 | zeros = [0. for i in range(n)] 81 | ones = [1. for i in range(m)] 82 | 83 | matrix = np.concatenate((matrix_a, np.eye(m)), axis=1) 84 | 85 | vector_c = np.array(zeros+ones) 86 | vector_x_start = np.array(zeros+vector_b.copy()) 87 | 88 | vector_x = main_stage_simplex_method( 89 | m, n + m, matrix, vector_b, -vector_c, vector_x_start, vector_jb) 90 | 91 | if vector_x is None: 92 | return None 93 | 94 | vector_x_0 = vector_x[:n] 95 | vector_x_u = vector_x[n:] 96 | 97 | if any(vector_x_0 < 0) or any(vector_x_u != 0): 98 | return () 99 | 100 | return vector_x_0 101 | 102 | 103 | def simplex(): 104 | m, n = map(int, input().split()) 105 | matrix_a = input_matrix(m) 106 | vector_b, vector_c = input_vector(), input_vector() 107 | vector_x = first_step_simplex_method(matrix_a, vector_b, m, n) 108 | 109 | if vector_x is None: 110 | return "Unbounded" 111 | elif len(vector_x) == 0: 112 | return "No solution" 113 | else: 114 | return f"Bounded\n{' '.join(map(str, vector_x))}" 115 | 116 | 117 | if __name__ == "__main__": 118 | print(simplex()) 119 | -------------------------------------------------------------------------------- /task4.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | 4 | 5 | def input_matrix(m): 6 | matrix = [] 7 | for el in range(m): 8 | matrix.append(list(map(int, input().split()))) 9 | return np.array(matrix) 10 | 11 | 12 | def input_vector(): 13 | return np.array(list(map(int, input().split()))) 14 | 15 | 16 | def get_inverted_matrix(matrix_b, vector_x, position): 17 | vector_l = matrix_b.dot(vector_x.T) 18 | 19 | if vector_l[position] == 0: 20 | return None 21 | 22 | vector_l_cover = vector_l[position] 23 | vector_l[position] = -1 24 | vector_l *= -1 / vector_l_cover 25 | matrix_b_new = matrix_b + vector_l.reshape(-1, 1) * matrix_b[position] 26 | matrix_b_new[position] -= matrix_b[position] 27 | 28 | return matrix_b_new 29 | 30 | 31 | def main_stage_simplex_method(matrix_a, vector_c, vector_x, vector_jb): 32 | m = len(matrix_a) 33 | n = len(matrix_a[0]) 34 | 35 | if m == n: 36 | return vector_x, vector_jb, None 37 | 38 | matrix_b = np.linalg.inv(matrix_a[:, vector_jb]) 39 | while True: 40 | delta = vector_c[vector_jb].dot(matrix_b).dot(matrix_a) - vector_c 41 | delta[vector_jb] = math.inf 42 | 43 | checker = -1 44 | for i, el in enumerate(delta): 45 | if el < 0: 46 | checker = i 47 | break 48 | if checker == -1: 49 | return vector_x, vector_jb, matrix_b 50 | 51 | j0 = checker 52 | 53 | vector_z = matrix_b.dot(matrix_a[:, j0]) 54 | 55 | if all([i <= 0 for i in vector_z]): 56 | return None, None, None 57 | 58 | theta = [vector_x[vector_jb[i]] / vector_z[i] if vector_z[i] > 0 else math.inf for i in range(m)] 59 | theta0 = min(theta) 60 | 61 | s = theta.index(theta0) 62 | vector_jb[s] = j0 63 | 64 | matrix_b = get_inverted_matrix(matrix_b, matrix_a[:, j0], s) 65 | 66 | if matrix_b is None: 67 | return None, None, None 68 | 69 | vector_x_new = np.zeros(n, dtype=float) 70 | vector_x_new[vector_jb] = vector_x[vector_jb] - theta0 * vector_z 71 | vector_x_new[j0] = theta0 72 | vector_x = vector_x_new 73 | 74 | 75 | def first_and_second_step_simplex_method(matrix_a, vector_b, vector_c): 76 | m = len(matrix_a) 77 | n = len(matrix_a[0]) 78 | 79 | for i in range(m): 80 | if vector_b[i] < 0: 81 | vector_b[i] *= -1 82 | matrix_a[i] *= -1 83 | 84 | vector_jb_cover = [i for i in range(n, n + m)] 85 | 86 | vector_c_cover = np.concatenate((np.zeros(n), np.ones(m))) 87 | vector_x = np.concatenate((np.zeros(n), np.copy(vector_b))) 88 | 89 | vector_x, vector_jb, matrix_b = main_stage_simplex_method( 90 | np.concatenate((matrix_a, np.eye(m)), axis=1), -vector_c_cover, vector_x, vector_jb_cover) 91 | 92 | if vector_x is None: 93 | return None 94 | 95 | vector_x_0 = vector_x[:n] 96 | 97 | if any(vector_x_0 < 0) or any(vector_x[n:] != 0): 98 | return () 99 | 100 | while True: 101 | vector_jb_n = [i for i in range(len(matrix_a[0])) if i not in vector_jb] 102 | 103 | checker = -1 104 | for i, el in enumerate(vector_jb): 105 | if el >= n: 106 | checker = i 107 | break 108 | 109 | if checker == -1: 110 | vector_x, vector_jb, matrix_b, = main_stage_simplex_method( 111 | matrix_a, vector_c, vector_x_0, vector_jb) 112 | return vector_x 113 | 114 | el_j_k = vector_jb[checker] 115 | i0 = el_j_k - n 116 | 117 | vector_e = np.zeros(m) 118 | vector_e[i0] = 1 119 | 120 | vector_of_alphas = vector_e.dot(matrix_b).dot(matrix_a[:, vector_jb_n]) 121 | 122 | if all(vector_of_alphas == 0): 123 | matrix_a = np.delete(matrix_a, i0, 0) 124 | matrix_b = np.delete(matrix_b, i0, 1) 125 | matrix_b = np.delete(matrix_b, checker, 0) 126 | vector_jb.remove(el_j_k) 127 | 128 | for i in range(len(vector_jb)): 129 | if vector_jb[i] > el_j_k: 130 | vector_jb[i] -= 1 131 | else: 132 | i = 0 133 | for a in vector_of_alphas: 134 | if a != 0: 135 | break 136 | i += 1 137 | 138 | j0 = vector_jb_n[i] 139 | vector_jb[checker] = j0 140 | 141 | 142 | def simplex(): 143 | m, n = map(int, input().split()) 144 | matrix_a = input_matrix(m) 145 | vector_b = input_vector() 146 | vector_c = input_vector() 147 | 148 | vector_x = first_and_second_step_simplex_method(matrix_a, vector_b, vector_c) 149 | 150 | if vector_x is None: 151 | return "Unbounded" 152 | elif len(vector_x) == 0: 153 | return "No solution" 154 | else: 155 | return f"Bounded\n{' '.join(map(str, vector_x))}" 156 | 157 | 158 | if __name__ == "__main__": 159 | print(simplex()) 160 | -------------------------------------------------------------------------------- /task5.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | 4 | def input_vector(): 5 | return list(map(int, input().split())) 6 | 7 | 8 | def input_matrix(m): 9 | matrix = [] 10 | for el in range(m): 11 | matrix.append(list(map(int, input().split()))) 12 | return matrix 13 | 14 | 15 | def shortest_paths(n, v0, adj, capacity, cost): 16 | vector_d = [math.inf for _ in range(n)] 17 | vector_d[v0] = 0 18 | inq = [False for _ in range(n)] 19 | q = [v0] 20 | p = [-1 for _ in range(n)] 21 | 22 | while len(q): 23 | u = q[0] 24 | del q[0] 25 | inq[u] = False 26 | for v in adj[u]: 27 | if capacity[u][v] > 0 and vector_d[v] > vector_d[u] + cost[u][v]: 28 | vector_d[v] = vector_d[u] + cost[u][v] 29 | p[v] = u 30 | if not inq[v]: 31 | inq[v] = True 32 | q.append(v) 33 | 34 | return vector_d, p 35 | 36 | 37 | def min_cost_flow(N, edges, K, s, t, n, m): 38 | adj = [[] for _ in range(N)] 39 | cost = [[0 for _ in range(N)] for _ in range(N)] 40 | capacity = [[0 for _ in range(N)] for _ in range(N)] 41 | 42 | for e in edges: 43 | adj[e[0]].append(e[1]) 44 | adj[e[1]].append(e[0]) 45 | cost[e[0]][e[1]] = e[3] 46 | cost[e[1]][e[0]] = -e[3] 47 | capacity[e[0]][e[1]] = e[2] 48 | 49 | flow = 0 50 | cost_s = 0 51 | 52 | while flow < K: 53 | vector_d, p = shortest_paths(N, s, adj, capacity, cost) 54 | if vector_d[t] == math.inf: 55 | break 56 | 57 | f = K - flow 58 | cur = t 59 | while cur != s: 60 | f = min(f, capacity[p[cur]][cur]) 61 | cur = p[cur] 62 | 63 | flow += f 64 | cost_s += f * vector_d[t] 65 | cur = t 66 | 67 | while cur != s: 68 | capacity[p[cur]][cur] -= f 69 | capacity[cur][p[cur]] += f 70 | cur = p[cur] 71 | 72 | ans = [[0 for _ in range(n)] for _ in range(m)] 73 | for i in range(m): 74 | for j in range(n): 75 | ans[i][j] = capacity[j + m + 1][i + 1] 76 | 77 | if flow < K: 78 | return None 79 | else: 80 | return ans 81 | 82 | 83 | def matrix_transport_task(): 84 | m, n = map(int, input().split(' ')) 85 | matrix_c = input_matrix(m) 86 | vector_a = input_vector() 87 | vector_b = input_vector() 88 | 89 | s = 0 90 | t = m + n + 1 91 | sum_a = 0 92 | sum_b = 0 93 | edges = [] 94 | 95 | for i in range(m): 96 | for j in range(n): 97 | edges.append([i + 1, m + j + 1, math.inf, matrix_c[i][j]]) 98 | 99 | for i in range(m): 100 | sum_a += vector_a[i] 101 | edges.append([0, i + 1, vector_a[i], 0]) 102 | 103 | for i in range(n): 104 | sum_b += vector_b[i] 105 | edges.append([m + i + 1, n + m + 1, vector_b[i], 0]) 106 | 107 | route = min_cost_flow(n + m + 2, edges, min(sum_a, sum_b), s, t, n, m) 108 | return '\n'.join([' '.join(list(map(str, map(int, i)))) for i in route]) 109 | 110 | 111 | if __name__ == '__main__': 112 | print(matrix_transport_task()) 113 | -------------------------------------------------------------------------------- /task6.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | from operator import sub 4 | 5 | 6 | def input_matrix(size): 7 | matrix = [] 8 | for el in range(size): 9 | matrix.append(list(map(float, input().split()))) 10 | return np.array(matrix) 11 | 12 | 13 | def input_vector(): 14 | return list(map(int, input().split())) 15 | 16 | 17 | def iterative_algorithm( 18 | m, n, matrix_a, matrix_d, vector_b, 19 | vector_c, vector_x, vector_j, vector_j_opt): 20 | 21 | eps = 1 * 10 ** -5 22 | 23 | while True: 24 | vector_c_x = vector_c + matrix_d.dot(vector_x) 25 | B = np.linalg.inv(matrix_a[:, vector_j]) 26 | 27 | delta = -vector_c_x[vector_j].dot(B).dot(matrix_a) + vector_c_x 28 | 29 | j0 = -1 30 | 31 | for i in range(n): 32 | if delta[i] + eps < 0: 33 | j0 = i 34 | break 35 | if j0 == -1: 36 | return vector_x 37 | 38 | vector_l = np.zeros(n) 39 | vector_l[j0] = 1 40 | 41 | matrix_a_opt = np.array(matrix_a[:, vector_j_opt]) 42 | matrix_h = np.vstack(( 43 | np.hstack((matrix_d[vector_j_opt][:, vector_j_opt], matrix_a_opt.T)), 44 | np.hstack((matrix_a_opt, np.zeros((m, m)))) 45 | )) 46 | 47 | vector_b = np.append(matrix_d[vector_j_opt, j0], matrix_a[:, j0]) 48 | vector_x_new = - np.linalg.inv(matrix_h).dot(vector_b) 49 | 50 | for i in range(len(vector_j_opt)): 51 | vector_l[vector_j_opt[i]] = vector_x_new[i] 52 | 53 | vector_d = vector_l.transpose().dot(matrix_d).dot(vector_l) 54 | 55 | thetas = [math.inf for i in range(n)] 56 | for i in vector_j_opt: 57 | thetas[i] = -vector_x[i]/vector_l[i] if vector_l[i] < -eps else math.inf 58 | 59 | thetas[j0] = math.inf if abs(vector_d) < eps else abs(delta[j0]) / vector_d 60 | 61 | min_theta = min(thetas) 62 | checker = thetas.index(min_theta) 63 | 64 | if min_theta == math.inf: 65 | return None 66 | 67 | vector_x = vector_x + min_theta * vector_l 68 | 69 | if checker == j0: 70 | vector_j_opt.append(checker) 71 | elif checker in vector_j_opt and checker not in vector_j: 72 | vector_j_opt.remove(checker) 73 | else: 74 | s = vector_j.index(checker) 75 | value_j_index = -1 76 | 77 | for j in [j for j in vector_j_opt if j not in vector_j]: 78 | if abs((B.dot(matrix_a[:, j]))[s]) > eps: 79 | value_j_index = j 80 | break 81 | 82 | if value_j_index != -1: 83 | vector_j[s] = value_j_index 84 | vector_j_opt.remove(checker) 85 | else: 86 | vector_j_opt[vector_j_opt.index(checker)] = j0 87 | vector_j[s] = j0 88 | 89 | 90 | def quadratic_programming(): 91 | m, n, k = map(int, input().split()) 92 | 93 | matrix_a = input_matrix(m) 94 | vector_b = np.array(input_vector()) 95 | vector_c = np.array(input_vector()) 96 | matrix_d = input_matrix(n) 97 | vector_x = np.array(list(map(float, input().split()))) 98 | vector_j = list(map(sub, input_vector(), [1 for i in range(m)])) 99 | vector_j_opt = list(map(sub, input_vector(), [1 for i in range(m)])) 100 | 101 | vector_x_new = iterative_algorithm( 102 | m, n, matrix_a, matrix_d, 103 | vector_b, vector_c, vector_x, vector_j, vector_j_opt) 104 | 105 | if vector_x_new is None: 106 | return "Unbounded" 107 | else: 108 | return f"Bounded\n{' '.join(map(str, vector_x_new))}" 109 | 110 | 111 | if __name__ == "__main__": 112 | print(quadratic_programming()) 113 | --------------------------------------------------------------------------------