Работа готова

This commit is contained in:
Сергей Полевой 2023-12-14 05:37:04 +04:00
commit ba713dca25
4 changed files with 217 additions and 0 deletions

BIN
misc/task.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

13
readme.md Normal file
View File

@ -0,0 +1,13 @@
# Лабораторная работа №1 по ВМ
___
## Состав команды №4 (ПИбд-33):
- ### Полевой Сергей
- ### Мочалов Данила
- ### Минхасапов Руслан
## Задание:
![Картинка задания](misc/task.jpg)

163
src/main.py Normal file
View File

@ -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)}')

41
src/utils.py Normal file
View File

@ -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)