【问题标题】:Scipy / Sympy to Optimize Multivariate SystemScipy / Sympy 优化多元系统
【发布时间】:2020-06-10 01:35:40
【问题描述】:

我正在尝试复制 Excel 的 Goal Seek 函数,它基于 Newton-Raphson。

就我而言,我想优化一组人(包括孩子)对孩子(组/孩子)的比率,按“Z”的某个比率目标来获得新的孩子数量;然后随着新孩子号码的变化而减少组号码。

示例: 假设我在一个组中有 1000 人,其中包括孩子,占 100...假设我的目标比率是 12(组/孩子)...要解决这个问题,我需要减少孩子们到 76 岁,这也将减少到 923 组。

伪公式将是 Group (1000 - X) / X,尽管需要先计算分母中的 X 值...

代码尝试:

from scipy import optimize

# inputs
group = 1000
kids = 100

# formula
def f(x, group):
    results = (group - x) / x
    return results

optimize.newton(f, 100, 1000)

这会导致 args 无法正确通过,但我只是不确定如何构造方程。

编辑:补充说我也不确定将新目标放在哪里......同时澄清我希望结果不低于目标。

【问题讨论】:

  • 您希望该值尽可能接近目标费率吗?还是应该不低于目标?
  • 感谢您的澄清问题...不低于目标。我将把它添加回问题:)
  • 在这种情况下 77 是错误的答案,因为 923/77 ~ 11.987
  • 大声笑,你是对的。所以孩子的数量大约是~76

标签: python optimization sympy scipy-optimize


【解决方案1】:

您只需要简单的数学运算即可。请注意:

(people - y) / y > target

因此,

people - y > target * y
people > (target + 1) * y
people / (target + 1) > y

应该从组中删除的孩子的数量需要满足

kids - floor(people / (target + 1))

在这种情况下,您得到 24。因此,孩子的数量等于 76,成人的数量等于 924。因此,924/76 ~ 12,16 > 12

【讨论】:

  • @Christopher:未知,但您可以使用您对人数和目标率的了解来计算。
【解决方案2】:

我通过https://github.com/DrTol/GoalSeek_Python找到了解决方案

def GoalSeek(fun,goal,x0,fTol=0.0001,MaxIter=1000):
    # Goal Seek function of Excel
    #   via use of Line Search and Bisection Methods

    # Inputs
    #   fun     : Function to be evaluated
    #   goal    : Expected result/output
    #   x0      : Initial estimate/Starting point

    # Initial check
    if fun(x0)==goal:
        print('Exact solution found')
        return x0

    # Line Search Method
    step_sizes=np.logspace(-1,4,6)
    scopes=np.logspace(1,5,5)

    vFun=np.vectorize(fun)

    for scope in scopes:
        break_nested=False
        for step_size in step_sizes:

            cApos=np.linspace(x0,x0+step_size*scope,int(scope))
            cAneg=np.linspace(x0,x0-step_size*scope,int(scope))

            cA=np.concatenate((cAneg[::-1],cApos[1:]),axis=0)

            fA=vFun(cA)-goal

            if np.any(np.diff(np.sign(fA))):

                index_lb=np.nonzero(np.diff(np.sign(fA)))

                if len(index_lb[0])==1:

                    index_ub=index_lb+np.array([1])

                    x_lb=np.asscalar(np.array(cA)[index_lb][0])
                    x_ub=np.asscalar(np.array(cA)[index_ub][0])
                    break_nested=True
                    break
                else: # Two or more roots possible

                    index_ub=index_lb+np.array([1])

                    print('Other solution possible at around, x0 = ', np.array(cA)[index_lb[0][1]])

                    x_lb=np.asscalar(np.array(cA)[index_lb[0][0]])
                    x_ub=np.asscalar(np.array(cA)[index_ub[0][0]])
                    break_nested=True
                    break

        if break_nested:
            break
    if not x_lb or not x_ub:
        print('No Solution Found')
        return

    # Bisection Method
    iter_num=0
    error=10

    while iter_num<MaxIter and fTol<error:

        x_m=(x_lb+x_ub)/2
        f_m=fun(x_m)-goal

        error=abs(f_m)

        if (fun(x_lb)-goal)*(f_m)<0:
            x_ub=x_m
        elif (fun(x_ub)-goal)*(f_m)<0:
            x_lb=x_m
        elif f_m==0:
            print('Exact spolution found')
            return x_m
        else:
            print('Failure in Bisection Method')

        iter_num+=1

    return x_m

运行函数

def fun(x):
    return (group - x) / x

print(GoalSeek(fun, goal, x0))

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 2016-03-10
    • 2021-08-26
    • 1970-01-01
    • 2013-05-07
    • 2012-10-08
    • 2020-08-25
    • 1970-01-01
    相关资源
    最近更新 更多