From ba713dca251d75786e09785b9a78d7b39e20cac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?= =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= Date: Thu, 14 Dec 2023 05:37:04 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=B3?= =?UTF-8?q?=D0=BE=D1=82=D0=BE=D0=B2=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- misc/task.jpg | Bin 0 -> 39793 bytes readme.md | 13 ++++ src/main.py | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.py | 41 +++++++++++++ 4 files changed, 217 insertions(+) create mode 100644 misc/task.jpg create mode 100644 readme.md create mode 100644 src/main.py create mode 100644 src/utils.py diff --git a/misc/task.jpg b/misc/task.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ed76e2d1e7b5e186a8a3490475209c7024a84c68 GIT binary patch literal 39793 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 Iv0tPA11LGoRsaA1 literal 0 HcmV?d00001 diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..6671616 --- /dev/null +++ b/readme.md @@ -0,0 +1,13 @@ +# Лабораторная работа №1 по ВМ + +___ + +## Состав команды №4 (ПИбд-33): + +- ### Полевой Сергей +- ### Мочалов Данила +- ### Минхасапов Руслан + +## Задание: + +![Картинка задания](misc/task.jpg) \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..d13d7a4 --- /dev/null +++ b/src/main.py @@ -0,0 +1,163 @@ +from collections import OrderedDict + +from utils import * + + +class SimplexColumn: + def __init__(self, coefficient: float, variable: Variable, values: list[float]): + self.coefficient: float = coefficient + self.variable: Variable = variable + self.inner: list[float] = values + self.delta: float | None = None + + +class Simplex: + def __init__(self, equations: list[Equation], function: Function): + self.function: Function = function + self.equations: list[Equation] = equations + self.variables: set[Variable] = set(literal.var for equation in equations for literal in equation.literals) + + self.b_variable: Variable = Variable("b") + + self.columns: list[SimplexColumn] = [ + SimplexColumn( + next(filter(lambda l: l.var == var, self.function.literals)).a, + var, + list( + next( + filter( + lambda l: l.var == var, + equation.literals + ) + ).a + for equation in self.equations + ) + ) + for var in sorted(self.variables) + ] + [SimplexColumn(0, self.b_variable, [equation.b for equation in equations])] + + self.base: list[Variable] = [ + var + for var in list(OrderedDict.fromkeys(literal.var for equation in equations for literal in equation.literals)) + if sum(self.column_by_var(var).inner) == 1 + ] + + def compute_deltas(self): + for column in self.columns: + column.delta = sum( + col.coefficient * val + for (col, val) in zip((self.column_by_var(base) + for base in self.base), + column.inner + ) + ) - column.coefficient + + def iteration(self) -> bool: + main_column = self.max_delta_column() + + if abs(main_column.delta) <= 0.00000000001: + return False + + main_column_values = main_column.inner.copy() + main_row_index = self.min_q_row() + + self.base[main_row_index] = main_column.variable + + for column in self.columns: + column.inner[main_row_index] /= main_column_values[main_row_index] + + for row in filter(lambda x: x != main_row_index, range(len(self.base))): + for column in self.columns: + column.inner[row] -= main_column_values[row] * column.inner[main_row_index] + + self.compute_deltas() + + return True + + def min_q_row(self) -> int: + pairs = filter( + lambda x: x[1] > 0, + zip( + range(len(self.base)), + self.max_delta_column().inner, + self.column_by_var(self.b_variable).inner + ) + ) + + return min(pairs, key=lambda x: x[2] / x[1])[0] + + def max_delta_column(self) -> SimplexColumn: + return max(self.columns, key=lambda c: c.delta) + + def min_delta_column(self) -> SimplexColumn: + return min(self.columns, key=lambda c: c.delta) + + def column_by_var(self, var: Variable): + return next(filter(lambda c: c.variable == var, self.columns)) + + def answer(self) -> tuple[float, list[Substitution]]: + substitutions = [Substitution(var, 0) for var in self.variables] + column = self.min_delta_column() + + for base, value in zip(self.base, column.inner): + next(filter(lambda s: s.var == base, substitutions)).value = value + + return self.function.compute(substitutions), substitutions + + def __str__(self): + result = '' + + result += 'C\t\t' + '\t\t'.join(str(column.coefficient) for column in self.columns) + '\n' + result += 'Базис\t' + '\t\t'.join(column.variable.name for column in self.columns) + '\n' + for i, base in enumerate(self.base): + result += f'{base.name}\t\t' + '\t'.join('{0:4.1f}'.format(column.inner[i]) for column in self.columns) + '\n' + + result += 'Дельта\t' + '\t'.join('{0:4.1f}'.format(column.delta) if column.delta is not None else '-' for column in self.columns) + '\n' + + return result + + +if __name__ == '__main__': + x1 = Variable('x1') + x2 = Variable('x2') + x3 = Variable('x3') + x4 = Variable('x4') + x5 = Variable('x5') + + func = Function( + [Literal(x1, 0), Literal(x2, 0), Literal(x3, 0), Literal(x4, 1), Literal(x5, -2)], + -1 + ) + + eqs = [ + Equation( + [Literal(x1, 1), Literal(x2, 0), Literal(x3, 0), Literal(x4, -1), Literal(x5, 1)], + 2 + ), + Equation( + [Literal(x1, 0), Literal(x2, 1), Literal(x3, 0), Literal(x4, 2), Literal(x5, 3)], + 7 + ), + Equation( + [Literal(x1, 0), Literal(x2, 0), Literal(x3, 1), Literal(x4, 1), Literal(x5, -2)], + 1 + ), + ] + + simplex = Simplex(eqs, func) + simplex.compute_deltas() + print(simplex) + + iteration = 1 + while simplex.iteration(): + print(f'\n\t============ Итерация {iteration} ============\t\n' + str(simplex)) + iteration += 1 + + func_value, substitutions = simplex.answer() + + print() + print(f'f = {func_value}') + print() + + for substitution in sorted(substitutions): + print(f'{substitution.var.name} = {"{0:2.2f}".format(substitution.value)}') diff --git a/src/utils.py b/src/utils.py new file mode 100644 index 0000000..7def41f --- /dev/null +++ b/src/utils.py @@ -0,0 +1,41 @@ +from dataclasses import dataclass + + +@dataclass(unsafe_hash=True, frozen=True, order=True) +class Variable: + name: str + + +@dataclass(unsafe_hash=True, order=True) +class Literal: + var: Variable + a: float + + +@dataclass(unsafe_hash=True, frozen=True) +class Equation: + literals: list[Literal] + b: float + + +@dataclass(unsafe_hash=True, order=True) +class Substitution: + var: Variable + value: float + + +@dataclass(unsafe_hash=True) +class Function: + literals: list[Literal] + tends: int + + def compute(self, substitutions: list[Substitution]) -> float: + result = 0 + + for literal, substitution in zip(sorted(self.literals), sorted(substitutions)): + result += literal.a * substitution.value + + return result + + def compute_with_tends(self, substitutions: list[Substitution]) -> float: + return -self.compute(substitutions) if self.tends == 1 else self.compute(substitutions) \ No newline at end of file