You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scipy.Optimize中IndexError排查:数组索引过多错误

Hey, let's break down why you're hitting that IndexError and fix it step by step:

What's Causing the Error?

There are two core issues here:

1. Your Constraint Function Isn't Receiving Required Arguments

When you defined your equality constraint, you forgot to pass the args parameter to create_const:

con1 = {'type': 'eq', 'fun': create_const}

scipy.optimize.minimize doesn't automatically share the args from your target function with constraints. So when the optimizer calls create_const, it only sends the optimization variable dy—your *args ends up empty. That makes arg = np.asarray(args) an empty array, and trying to access arg[0, i] throws the index error.

2. Argument Parsing Logic is Broken

When you tested create_const(dy0, arg), you passed the entire arg tuple as a single argument. This meant *args became (arg,), so np.asarray(args) was a 2D array (shape (1, N)), and arg[0, i] worked. But when you correctly pass args to the constraint, *args will be all the individual elements of arg (like type_x[0], type_x[1], ..., delta2[2]), making np.asarray(args) a 1D array. Trying to use 2D indexing ([0, i]) on a 1D array will fail.

How to Fix It

Let's resolve both issues:

Step 1: Pass Arguments to the Constraint

Update your constraint dictionary to include the args parameter, wrapping arg in a tuple so it's passed as a single argument to create_const:

con1 = {'type': 'eq', 'fun': create_const, 'args': (arg,)}

Step 2: Fix Argument Parsing in create_const

Adjust the function to accept the entire arg tuple as a single parameter, then index it correctly (since it's now a 1D array):

def create_const(dy, arg):  # Remove *args, take arg as a single parameter
    arg = np.asarray(arg)
    n = np.shape(dy)[0]
    dx = np.zeros((n, 2))
    type_x = np.zeros(n, dtype=object)  # Use object dtype to hold string values
    delta1 = np.zeros(n)
    delta2 = np.zeros(n)
    gamma = np.zeros((n, n))
    
    for i in range(n):
        # arg[i] corresponds to type_x[i]
        a, b = bndr(arg[i])
        # delta1 starts at index n+1 (after n type_x elements + 1 dP value)
        delta1[i] = arg[n + 1 + i]
        # delta2 starts at index 2n+1
        delta2[i] = arg[2*n + 1 + i]
        dx[i, 0] = (b - a) * dy[i]
    
    # Note: dx[:,1] remains all zeros here—double-check if this is intentional for your logic
    gamma = GammaApprox(delta1, delta2, dx[:, 1], dx[:, 0])
    d = np.dot(delta2, dx[:, 0])
    g = np.dot(dx[:, 0], gamma)
    g = np.dot(g, dx[:, 0])
    dP = float(arg[n])  # dP is at index n (right after the n type_x elements)
    
    return d + 0.5 * g - dP

Step 3: Keep Your Test Call Valid

Since we adjusted create_const to take arg as a single parameter, your existing test line works as-is:

testconst = create_const(dy0, arg)

Quick Side Check

You might want to verify the dx[:,1] assignment in create_const—right now it's initialized to zero but never updated. That could lead to unexpected results in GammaApprox, so make sure that's intentional for your use case.

Full Modified Code

Here's the complete code with all fixes applied:

from scipy.optimize import minimize
import numpy as np

def totaldist(dy):
    n = np.shape(dy)[0]
    temp = 0
    for i in range(n):
        temp += dy[i] ** 2
    return -0.5 * temp

def create_bond(dy_max):
    n = np.shape(dy_max)[0]
    bond = np.zeros((n, 2))
    for i in range(n):
        bond[i, :] = [0, dy_max[i]]
    tot = tuple([tuple(row) for row in bond])
    return tot

def create_const(dy, arg):
    arg = np.asarray(arg)
    n = np.shape(dy)[0]
    dx = np.zeros((n, 2))
    type_x = np.zeros(n, dtype=object)
    delta1 = np.zeros(n)
    delta2 = np.zeros(n)
    gamma = np.zeros((n, n))
    
    for i in range(n):
        a, b = bndr(arg[i])
        delta1[i] = arg[n + 1 + i]
        delta2[i] = arg[2*n + 1 + i]
        dx[i, 0] = (b - a) * dy[i]
    
    gamma = GammaApprox(delta1, delta2, dx[:, 1], dx[:, 0])
    d = np.dot(delta2, dx[:, 0])
    g = np.dot(dx[:, 0], gamma)
    g = np.dot(g, dx[:, 0])
    dP = float(arg[n])
    
    return d + 0.5 * g - dP

def GammaApprox(delta1, delta2, x1, x2):
    n = np.shape(delta1)[0]
    gamma = np.zeros((n, n))
    for i in range(n):
        if x2[i] == x1[i]:
            gamma[i, i] = 0
        else:
            gamma[i, i] = (delta2[i] - delta1[i]) / (x2[i] - x1[i])
    return gamma

def GetNewPoint(x1, x2, delta1, delta2, type_x, P):
    n = np.shape(delta1)[0]
    dmax = np.zeros(n)
    dy0 = np.zeros(n)
    
    for i in range(n):
        a, b = bndr(type_x[i])
        if x2[i] > x1[i]:
            dmax[i] = (x2[i] - x1[i])/(b - a)
            dy0[i] = 1 / (b - a) * (x2[i] - x1[i]) / 2
        else:
            dmax[i] = (x1[i] - x2[i])/(b - a)
            dy0[i] = 1 / (b - a) * (x1[i] - x2[i]) / 2
    
    bond = create_bond(dmax)
    arg = ()
    for i in range(n):
        arg = arg + (type_x[i],)
    arg = arg + (abs(P[0] - P[1]), )
    for i in range(n):
        arg = arg + (delta1[i], )
    for i in range(n):
        arg = arg + (delta2[i], )
    
    testconst = create_const(dy0, arg)
    con1 = {'type': 'eq', 'fun': create_const, 'args': (arg,)}
    cons = ([con1, ])
    
    solution = minimize(totaldist, dy0, args=arg, method='SLSQP', bounds=bond, constraints=cons, options={'disp': True})
    x = solution.x
    print(x)
    return x

def bndr(type_x):
    if type_x == 'normal':
        x_0 = -5
        x_f = 1.5
    if type_x == 'lognorm':
        x_0 = 0.0001
        x_f = 5
    if type_x == 'chisquare':
        x_0 = 0.0001
        x_f = (0.8 * (10 ** .5))
    return x_0, x_f

def test():
    x1 = np.array([0.0001, 0.0001, -5])
    x2 = np.array([1.6673, 0.84334, -5])
    delta1 = np.array([0, 0, 0])
    delta2 = np.array([2.44E-7, 2.41E-6, 4.07E-7])
    type_x = np.array(['lognorm', 'chisquare', 'normal'])
    P = (0, 6.54E-8)
    f = GetNewPoint(x1, x2, delta1, delta2, type_x, P)
    return f

test()

内容的提问来源于stack exchange,提问作者Benji_90210

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:30:21