commit ba713dca251d75786e09785b9a78d7b39e20cac9 Author: Сергей Полевой Date: Thu Dec 14 05:37:04 2023 +0400 Работа готова diff --git a/misc/task.jpg b/misc/task.jpg new file mode 100644 index 0000000..ed76e2d Binary files /dev/null and b/misc/task.jpg differ 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