librairiesに頼らずにこれをそのまま実行したい場合は、Pythonに関連する問題ではないと思います。このような方程式を見つけたい場合は、これらの方程式を解くために必要な経験則を記述する必要があります。
まず、方程式を表す必要があります。どのような分離について:
- オペランド:
- シンボリックオペランド(a、b)は
- 数値オペランド(1,2)
- 演算子:
- 単項演算子( - 、trig関数)
- バイナリ演算子(+、 - 、*、/)
単項演算子は明らかに1つのオペランドを同封します、バイナリOPSは2を同封します。
どのような種類ですか?
私は、これらのコンポーネントのすべてが単一の共通のexpression
タイプから派生する必要があると思います。 そして、このクラスには式内のシンボルをすばやく見つける方法があります(getsymbols
)。
そして単項および二項演算子を区別し、いくつかの基本的な補完/再発注プリミティブを追加...のような
何か:セットアップし、この基本的な構造により
class expression(object):
def symbols(self):
if not hasattr(self, '_symbols'):
self._symbols = self._getsymbols()
return self._symbols
def _getsymbols(self):
"""
return type: list of strings
"""
raise NotImplementedError
class operand(expression): pass
class symbolicoperand(operand):
def __init__(self, name):
self.name = name
def _getsymbols(self):
return [self.name]
def __str__(self):
return self.name
class numericoperand(operand):
def __init__(self, value):
self.value = value
def _getsymbols(self):
return []
def __str__(self):
return str(self.value)
class operator(expression): pass
class binaryoperator(operator):
def __init__(self, lop, rop):
"""
@type lop, rop: expression
"""
self.lop = lop
self.rop = rop
def _getsymbols(self):
return self.lop._getsymbols() + self.rop._getsymbols()
@staticmethod
def complementop():
"""
Return complement operator:
op.complementop()(op(a,b), b) = a
"""
raise NotImplementedError
def reorder():
"""
for op1(a,b) return op2(f(b),g(a)) such as op1(a,b) = op2(f(a),g(b))
"""
raise NotImplementedError
def _getstr(self):
"""
string representing the operator alone
"""
raise NotImplementedError
def __str__(self):
lop = str(self.lop)
if isinstance(self.lop, operator):
lop = '(%s)' % lop
rop = str(self.rop)
if isinstance(self.rop, operator):
rop = '(%s)' % rop
return '%s%s%s' % (lop, self._getstr(), rop)
class symetricoperator(binaryoperator):
def reorder(self):
return self.__class__(self.rop, self.lop)
class asymetricoperator(binaryoperator):
@staticmethod
def _invert(operand):
"""
div._invert(a) -> 1/a
sub._invert(a) -> -a
"""
raise NotImplementedError
def reorder(self):
return self.complementop()(self._invert(self.rop), self.lop)
class div(asymetricoperator):
@staticmethod
def _invert(operand):
if isinstance(operand, div):
return div(self.rop, self.lop)
else:
return div(numericoperand(1), operand)
@staticmethod
def complementop():
return mul
def _getstr(self):
return '/'
class mul(symetricoperator):
@staticmethod
def complementop():
return div
def _getstr(self):
return '*'
class add(symetricoperator):
@staticmethod
def complementop():
return sub
def _getstr(self):
return '+'
class sub(asymetricoperator):
@staticmethod
def _invert(operand):
if isinstance(operand, min):
return operand.op
else:
return min(operand)
@staticmethod
def complementop():
return add
def _getstr(self):
return '-'
class unaryoperator(operator):
def __init__(self, op):
"""
@type op: expression
"""
self.op = op
@staticmethod
def complement(expression):
raise NotImplementedError
def _getsymbols(self):
return self.op._getsymbols()
class min(unaryoperator):
@staticmethod
def complement(expression):
if isinstance(expression, min):
return expression.op
else:
return min(expression)
def __str__(self):
return '-' + str(self.op)
、次のことができるようにすべきです非常に簡単な方程式を解く簡単なヒューリスティックを記述します。方程式を解くために学んだ簡単なルールを考えて、それらを書き留めておきましょう。それは動作するはずです:)そして
、非常にナイーブソルバー:
def solve(left, right, symbol):
"""
@type left, right: expression
@type symbol: string
"""
if symbol not in left.symbols():
if symbol not in right.symbols():
raise ValueError('%s not in expressions' % symbol)
left, right = right, left
solved = False
while not solved:
if isinstance(left, operator):
if isinstance(left, unaryoperator):
complementor = left.complement
right = complementor(right)
left = complementor(left)
elif isinstance(left, binaryoperator):
if symbol in left.rop.symbols():
left = left.reorder()
else:
right = left.complementop()(right, left.rop)
left = left.lop
elif isinstance(left, operand):
assert isinstance(left, symbolicoperand)
assert symbol==left.name
solved = True
print symbol,'=',right
a,b,c,d,e = map(symbolicoperand, 'abcde')
solve(a, div(add(b,mul(c,d)),e), 'd') # d = ((a*e)-b)/c
solve(numericoperand(1), min(min(a)), 'a') # a = 1
IMHO Windows上で実行されていないパッケージの大規模な集約であるSAGEの代わりに、ここでSymPyを指し示すほうがはるかに優れています(ただし、仮想マシンは例外ですが、これは数えません)。 –