2016-12-10 1 views
0

python 3.4で以下を必要とするタスクをプログラムする必要があります: - プログラムは、いくつかのサブモデルによって作成されたデータモデルを、次ユーザーがpython関数として入力したモデルを評価してください

# the program ask : 
please input the submodel1 
# user will input: 
A = a*x + b*y*exp(3*c/d*x) 
# then the program ask : 
-> please input the submodel2 
# user will input: 
B = e*x + f*y*exp(3*h/d*x) 
# then the program ask : 
-> please input the main model: 
# user will input: 
Y = A*x - exp(B**2/y) 

は、プログラムは、これらのモデル(文字列)を取得し、既存のデータ及びプロットのメインモデルのカーブフィッティングのようにそれらの上にいくつかの操作を実行すると、パラメータ値を示すと生じます。 ここでのアイデアは、アプリ内で関数としてプログラムする必要なく、実行時にモデルを選択する自由をユーザに与えることです。 ここで私の問題は、値を返すPython関数として文字列を変換または解釈することにあります。私はevalの()関数のような解決策を探ったが、もしあれば簡単に 希望は、私は、自分自身を明らかにした私は、あなたがそれに対処することができます無名関数を作成しますMatLabの

func = sym('string') 
func = matlabfunction(func) 

のようなソリューションを探していますさらに明確化が ソリューションは、事前に3.4 感謝のpythonと互換性があり、私に知らせてください必要

答えて

0

あなたから解析を使用することができます:数式を認識する https://pypi.python.org/pypi/parse とあなたのパーサを訓練、 は、この例を参照してください(python27) :
http://www.nerdparadise.com/tech/python/parsemath/

# A really simple expression evaluator supporting the 
# four basic math functions, parentheses, and variables. 

class Parser: 
    def __init__(self, string, vars={}): 
     self.string = string 
     self.index = 0 
     self.vars = { 
      'pi' : 3.141592653589793, 
      'e' : 2.718281828459045 
      } 
     for var in vars.keys(): 
      if self.vars.get(var) != None: 
       raise Exception("Cannot redefine the value of " + var) 
      self.vars[var] = vars[var] 

    def getValue(self): 
     value = self.parseExpression() 
     self.skipWhitespace() 
     if self.hasNext(): 
      raise Exception(
       "Unexpected character found: '" + 
       self.peek() + 
       "' at index " + 
       str(self.index)) 
     return value 

    def peek(self): 
     return self.string[self.index:self.index + 1] 

    def hasNext(self): 
     return self.index < len(self.string) 

    def skipWhitespace(self): 
     while self.hasNext(): 
      if self.peek() in ' \t\n\r': 
       self.index += 1 
      else: 
       return 

    def parseExpression(self): 
     return self.parseAddition() 

    def parseAddition(self): 
     values = [self.parseMultiplication()] 
     while True: 
      self.skipWhitespace() 
      char = self.peek() 
      if char == '+': 
       self.index += 1 
       values.append(self.parseMultiplication()) 
      elif char == '-': 
       self.index += 1 
       values.append(-1 * self.parseMultiplication()) 
      else: 
       break 
     return sum(values) 

    def parseMultiplication(self): 
     values = [self.parseParenthesis()] 
     while True: 
      self.skipWhitespace() 
      char = self.peek() 
      if char == '*': 
       self.index += 1 
       values.append(self.parseParenthesis()) 
      elif char == '/': 
       div_index = self.index 
       self.index += 1 
       denominator = self.parseParenthesis() 
       if denominator == 0: 
        raise Exception(
         "Division by 0 kills baby whales (occured at index " + 
         str(div_index) + 
         ")") 
       values.append(1.0/denominator) 
      else: 
       break 
     value = 1.0 
     for factor in values: 
      value *= factor 
     return value 

    def parseParenthesis(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char == '(': 
      self.index += 1 
      value = self.parseExpression() 
      self.skipWhitespace() 
      if self.peek() != ')': 
       raise Exception(
        "No closing parenthesis found at character " 
        + str(self.index)) 
      self.index += 1 
      return value 
     else: 
      return self.parseNegative() 

    def parseNegative(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char == '-': 
      self.index += 1 
      return -1 * self.parseParenthesis() 
     else: 
      return self.parseValue() 

    def parseValue(self): 
     self.skipWhitespace() 
     char = self.peek() 
     if char in '.': 
      return self.parseNumber() 
     else: 
      return self.parseVariable() 

    def parseVariable(self): 
     self.skipWhitespace() 
     var = '' 
     while self.hasNext(): 
      char = self.peek() 
      if char.lower() in '_abcdefghijklmnopqrstuvwxyz': 
       var += char 
       self.index += 1 
      else: 
       break 

     value = self.vars.get(var, None) 
     if value == None: 
      raise Exception(
       "Unrecognized variable: '" + 
       var + 
       "'") 
     return float(value) 

    def parseNumber(self): 
     self.skipWhitespace() 
     strValue = '' 
     decimal_found = False 
     char = '' 

     while self.hasNext(): 
      char = self.peek()    
      if char == '.': 
       if decimal_found: 
        raise Exception(
         "Found an extra period in a number at character " + 
         str(self.index) + 
         ". Are you European?") 
       decimal_found = True 
       strValue += '.' 
      elif char in '': 
       strValue += char 
      else: 
       break 
      self.index += 1 

     if len(strValue) == 0: 
      if char == '': 
       raise Exception("Unexpected end found") 
      else: 
       raise Exception(
        "I was expecting to find a number at character " + 
        str(self.index) + 
        " but instead I found a '" + 
        char + 
        "'. What's up with that?") 

     return float(strValue) 

def evaluate(expression, vars={}): 
    try: 
     p = Parser(expression, vars) 
     value = p.getValue() 
    except Exception as (ex): 
     msg = ex.message 
     raise Exception(msg) 

    # Return an integer type if the answer is an integer 
    if int(value) == value: 
     return int(value) 

    # If Python made some silly precision error 
    # like x.99999999999996, just return x + 1 as an integer 
    epsilon = 0.0000000001 
    if int(value + epsilon) != int(value): 
     return int(value + epsilon) 
    elif int(value - epsilon) != int(value): 
     return int(value) 

    return value 

print evaluate("1 + 2 * 3") 
print evaluate("(1 + 2) * 3") 
print evaluate("-(1 + 2) * 3") 
print evaluate("(1-2)/3.0 + 0.0000") 
print evaluate("1 + pi/4") 
print evaluate("(a + b)/c", { 'a':1, 'b':2, 'c':3 }) 
print evaluate("(x + e * 10)/10", { 'x' : 3 }) 
print evaluate("1.0/3 * 6") 
print evaluate("(1 - 1 + -1) * pi") 
print evaluate("pi * e") 
+0

非常にありがとうHamza、それは私が求めている解決策のこのようなものです、とにかくこれは私に強いスタートポイントを与えました – Hzine

+0

@hamza hebal答えに関連するテキストを追加できました。リンクがなくなるなら、この答えは価値がないでしょう。ありがとう。 – rapvelopment

0

lmfit(http://lmfit.github.io/lmfit-py/は)あなたが役に立つかもしれませんExpressionModelがあります

import numpy as np 
import matplotlib.pyplot as plt 
from lmfit.models import ExpressionModel 

# make fake data 
x = np.linspace(-10, 10, 201) 
amp, cen, wid = 3.4, 1.8, 0.5 

y = amp * np.exp(-(x-cen)**2/(2*wid**2))/(np.sqrt(2*np.pi)*wid) 
y += np.random.normal(size=len(x), scale=0.01) 

# create model from expression 
model= ExpressionModel("amp * exp(-(x-cen)**2 /(2*wid**2))/(sqrt(2*pi)*wid)") 

# fit data to that model 
result = model.fit(y, x=x, amp=5, cen=5, wid=1) 

# show results 
print(result.fit_report()) 
plt.plot(x, y,   'bo') 
plt.plot(x, result.init_fit, 'k--') 
plt.plot(x, result.best_fit, 'r-') 
plt.show() 

これはasteval(http://newville.github.io/asteval)を使用しているため、かなり豊富なPython構文とnumpy定数とufuncのサブセットをサポートしています(sqrtexpsinpiなど)。

+0

ありがとうございましたNewville、これは大部分のケースで素晴らしいですし、私のケースでは私がカスタマイズされたパーサーを使用する必要がありますが、これは最高の答え、ありがとう – Hzine

関連する問題