2017-10-13 5 views
0

J'essaye d'écrire une fonction pour résoudre le problème d'une variable d'une autre fonction en python, un peu comme ce que fait le solveur Excel. Pour simplifier mon exemple, j'ai une fonction qui prend en compte plusieurs variables puis calculer un prix. Je transmettrai des valeurs réelles (a, b, c, d, x) dans cette fonction afin qu'elle renvoie une valeur numérique.retour résoudre pour une variable en utilisant python

def calc_price(a,b,c,d,x): 
    value = a+b*c-d + x 
    return value 

Maintenant, on me donne un prix cible, et a, b, c, d. Seule inconnue est la variable x, donc je veux revenir à la variable x. Je veux construire ceci dans une fonction qui prend dans les mêmes variables que calc_price, avec une variable supplémentaire target_price.

def solve(target_price, a,b,c,d): 
    #this function takes in values for target_price, a,b,c,d 
    #and should do something like this: 
    target_price = calc_price(a,b,c,d,x) 
    solve for x <---------this is the part I'm not sure how to do 
    return x 

J'ai créé une fonction comme ceci ci-dessous pour revenir résoudre la valeur x par une boucle, mais il est inefficace dans le calcul de grands ensembles de données, donc je suis à la recherche d'une solution plus efficace.

def solve(target_price,a,b,c,d): 
    x = 0.01 
    while x < 1: 
     if abs(target_price - calc_price(a,b,c,d,x)) < 0.001: 
      return x 
     x += 0.001 

Merci!

+1

[scipy.optimize.minimize_scalar] (https://docs.scipy.org/doc/scipy-0.19.1/reference/generated /scipy.optimize.minimize_scalar.html). Ce sera l'étalon-or (en méthodes numériques, chercher des systèmes d'algèbre informatique pour l'autre monde, pas nécessairement recommandé). Si c'est un code trop lourd/lib-dépendance: recherchez root-finding et co. – sascha

+1

@sascha, ne vous voulez pas dire la norme 'Golden' :-) https://docs.scipy.org/doc/scipy-0.19.1/reference/optimize.minimize_scalar-golden.html –

+0

Assez sympa Stuart. Mais je voudrais utiliser brent (au moins quand quelqu'un l'a déjà mis en œuvre pour moi) :-) – sascha

Répondre

0

Considérez ceci comme une démo (car votre tâche est encore un peu floue) et assurez-vous de lire scipy's docs pour connaître les garanties de base fournies par cette méthode. On pourrait argumenter qu'une approche basée sur root-finding est plus appropriée (nous minimisons une fonction ici, donc la construction abs dans la fonction résiduelle), mais cette approche n'a pas besoin de donner quelques parenthèses. intervalle.

code:

import numpy as np 
from scipy.optimize import minimize_scalar 
np.random.seed(0) 

""" Utils """ 
def calc_price(x, a, b, c, d): 
    value = a+b*c-d + x 
    return value 

def calc_price_res(x, target, a, b, c, d): 
    value = a+b*c-d + x 
    return abs(value - target) # we are looking for f(x) == 0 

""" Create fake-data (typically the job of OP!) """ 
a, b, c, d, x = np.random.random(size=5) 
fake_target = calc_price(x, a, b, c, d) 

print('a, b, c, d: ', a, b, c, d) 
print('real x: ', x) 
print('target: ', fake_target) 
print('noisy obj (just to be sure): ', calc_price_res(x, fake_target, a, b, c, d)) 

""" Solve """ 
res = minimize_scalar(calc_price_res, args=(fake_target, a, b, c, d)) 

print('optimized x: ', res.x) 
print('optimized fun: ', res.fun) 

Sortie:

a, b, c, d: 0.548813503927 0.715189366372 0.602763376072 0.544883182997 
real x: 0.423654799339 
target: 0.858675077275 
noisy obj (just to be sure): 0.0 
optimized x: 0.423654796297 
optimized fun: 3.04165614917e-09 
+1

merci c'est exactement ce que je cherchais. Je ne savais pas comment passer les autres variables mais vous l'avez fait très clair dans l'exemple! cette fonction minimize_scalar est aussi beaucoup plus rapide que ma fonction d'origine. – jingz