#python #list
Вопрос:
У меня всегда была эта сумасшедшая и, возможно, нелогичная идея перед всеми моими «домашними экзаменами», что я могу создать список всех возможных комбинаций всех формул. Сделав это, я мог бы ввести некоторые базовые значения в различные переменные, которые у меня есть в тесте, и получить список формул, соответствующих задаче. Основной пример:
Закон Ома
U = R * I
Закон Джоулей
P = U * I
но эти два списка можно объединить:
P = R * I * I
или
I = U / R
что подразумевает
P = U * U / R
Как бы можно было создать все возможные комбинации этих списков? Сначала я подумал о создании различных списков, таких как
ohms_law = ['R', 'U', 'I']
jouls_law = ['P', 'U', 'I']
.
.
.
однако это вопрос фактического их соединения, а также вопрос о том, где поставить фактический знак равенства, знак деления и т. Д.
Может ли кто-нибудь помочь мне приблизиться к завершению этой невероятно неэффективной и бесполезной идеи? Просто для удовольствия.
Правка: Для людей с более низким уровнем образования, которые никогда не использовали формулы.
Formula 1: U = R * I
Formula 2: P = U * I
Output:
U = R * I
P = U * I
P = U * U / R
P = I * I * R
R = U / I
I = U / R
U = P / I
.
.
.
cont.
то, что я здесь делаю, — это просто сопоставление формул друг с другом. Первая формула говорит, что U равно I раз R. Это означает, что мы можем вставить это во вторую формулу, чтобы получить новую формулу. Мне нужны все эти комбинации.
Комментарии:
1. Я не совсем понимаю, что вы пытаетесь сделать. Не могли бы вы предоставить некоторые примеры выходных данных? Я думаю, что это сделает все немного более ясным.
2. @Inogueir Я привел примеры.
Ответ №1:
Вот такое предложение. Конечный результат неверен, я не хотел тратить слишком много времени на исправление ошибок, но вы можете видеть, как я пытался решить проблему.
import typing
from dataclasses import dataclass
@dataclass
class Unit: # as in Physical Quantity
name: str
R = Unit("R")
U = Unit("U")
I = Unit("I")
P = Unit("P")
units = [R, U, I, P]
@dataclass
class Factor:
unit: Unit
dimension: int # should not be zero
def pretty(self) -> str:
operand_sign = "*" if self.dimension > 0 else "/"
return f"{operand_sign} {operand_sign.join(' ' self.unit.name ' ' for _ in range(abs(self.dimension)))}"
@dataclass
class Formula: # only considering its quantities
result: Unit
factors: typing.List[Factor]
def pretty(self) -> str:
# TODO: this formatting is ugly, it produces "R = / I * U " for example
return f"{self.result.name} = " " ".join(factor.pretty() for factor in self.factors)
ohms_law = Formula(U, [Factor(R, 1), Factor(I, 1)])
jouls_law = Formula(P, [Factor(U, 1), Factor(I, 1)])
# now we have to rewrite each formula in each combination of its factors/result
def reformulate(formula: Formula, unit: Unit) -> Formula:
# FIXME: I am sure this function is incorrect, notably if unit is not of dimension -1 in the base formula
assert unit in (_factor.unit for _factor in formula.factors)
new_formula = Formula(
result=unit,
factors=[
Factor(_factor.unit, dimension=-_factor.dimension)
for _factor in formula.factors if _factor.unit != unit
] [
Factor(formula.result, dimension=1)
]
)
return new_formula
base_formulas = [ohms_law, jouls_law]
print("base formulas:")
for base_formula in base_formulas:
print(base_formula.pretty())
formulas = base_formulas [
reformulate(base_formula, factor.unit)
for base_formula in base_formulas
for factor in base_formula.factors
]
print("base reformulations:")
for formula in formulas:
print(formula.pretty())
# it will be handy to know, for each quantity, which formula can produce it
formulas_by_unit: typing.Dict[str, typing.List[Formula]] = {
unit.name: # NOTE: we have to hash by `unit.name` because a Unit is not simply hashable, but a string is
[formula for formula in formulas
if (unit == formula.result)]
for unit in units
}
print("possible formulas for substitution:")
print("n".join(unit_name ": " str([formula.pretty() for formula in formulas])
for unit_name, formulas in formulas_by_unit.items()))
# now that we have set the data and its structure, we can create new formulas
def substitute(formula1: Formula, common_unit: Unit, formula2: Formula) -> Formula:
"""Replace the common_unit from formula1 with its definition from formula2."""
return Formula(
result=formula1.result,
factors=merge_factors(
# FIXME: take into account that the factor from formula1 may have a dimension != 1
[factor for factor in formula1.factors if factor.unit != common_unit],
formula2.factors
)
)
def merge_factors(factors1: typing.List[Factor], factors2: typing.List[Factor]) -> typing.List[Factor]:
"""Merge the two lists of factors, combining those of the same unit by adding their dimension."""
factors1_by_unit = {factor.unit.name: factor for factor in factors1}
factors2_by_unit = {factor.unit.name: factor for factor in factors2}
units_only_in_factors1 = set(factors1_by_unit.keys()).difference(factors2_by_unit)
units_only_in_factors2 = set(factors2_by_unit.keys()).difference(factors1_by_unit)
units_in_both = set(factors1_by_unit.keys()).intersection(factors2_by_unit)
return [
*(factors1_by_unit[unit_name] for unit_name in units_only_in_factors1),
*(factors2_by_unit[unit_name] for unit_name in units_only_in_factors2),
*(
Factor(unit=Unit(unit_name), dimension=factor1.dimension factor2.dimension)
for unit_name in units_in_both
for factor1 in (factors1_by_unit[unit_name],)
for factor2 in (factors2_by_unit[unit_name],)
if factor1.dimension factor2.dimension != 0
)
]
print("reformulations:")
for base_unit in units:
for base_formula in formulas_by_unit[base_unit.name]:
# find possible substitutions
for substituable_factor in base_formula.factors:
for candidate_substitution_formula in formulas_by_unit[substituable_factor.unit.name]:
if base_unit not in (factor.unit for factor in candidate_substitution_formula.factors):
reformulation = substitute(base_formula, substituable_factor.unit, candidate_substitution_formula)
print(reformulation.pretty())
base formulas:
U = * R * I
P = * U * I
base reformulations:
U = * R * I
P = * U * I
R = / I * U
I = / R * U
U = / I * P
I = / U * P
possible formulas for substitution:
R: ['R = / I * U ']
U: ['U = * R * I ', 'U = / I * P ']
I: ['I = / R * U ', 'I = / U * P ']
P: ['P = * U * I ']
reformulations:
R = * P
R = * P / I / I
P = * R * I * I
P = / R * U * U
Например, первый результат R = * P
-это то, что неверно !
Он пытается переформулировать 'R = / I * U '
с 'I = / U * P '
помощью . Но у I есть размерность -1, которая не принимается во внимание. Таким образом , он видит два U
, один из измерения 1, один из измерения -1, и отменяет их.
Помимо ошибок, вы должны быть в состоянии понять, как я действовал.