使用Pulp建模非方阵时遭遇索引越界问题求助
Hey there! Let's break down why you're hitting that IndexError: list index out of range and get your model working with non-square matrices like your target 365×24 setup.
The Root Cause
The problem lies in how you're constructing your Excel data matrices (TEST, YAPR, MAPR) versus how you're accessing them later.
Looking at your matrix-building code:
TEST = [[sheet11.cell_value(i,j) for i in range(YPER)] for j in range(HE)]
This creates a column-first matrix: the outer loop iterates over columns (j, 0-5 for HE=6), and the inner loop over rows (i, 0-4 for YPER=5). The result is a 6-row × 5-column structure where TEST[j][i] maps to Excel's cell (i,j).
But later in your constraint, you're trying to access it as TEST[i][j]—treating it like a row-first matrix. Since each sublist in TEST only has 5 elements (one per row), when j hits 5 (the 6th column), you're trying to access an index that doesn't exist in the sublist, hence the error.
The Fix
You have two straightforward options, but the first is more intuitive and aligns with standard row-first thinking:
Option 1: Build Row-First Matrices
Adjust your list comprehensions to iterate over rows first, then columns. This creates a YPER×HE matrix (5×6 for your test case) where TEST[i][j] directly maps to Excel's cell (i,j):
# Build matrices row-first to match your variable indexing TEST = [[sheet11.cell_value(i,j) for j in range(HE)] for i in range(YPER)] YAPR = [[sheet12.cell_value(i,j) for j in range(HE)] for i in range(YPER)] MAPR = [[sheet13.cell_value(i,j) for j in range(HE)] for i in range(YPER)]
Option 2: Adjust Indexing When Accessing Matrices
If you prefer to keep the column-first matrix build, swap the indices when accessing the values in your constraint:
model += pulp.lpSum([YAHL[i][j] + MAHL[i][j]]) == TEST[j][i]
But Option 1 is cleaner and less prone to future mix-ups, especially as you scale to larger matrices like 365×24.
Bonus: Simplify Your Constraint
You can also remove the unnecessary brackets around TEST[i][j]—you're comparing a scalar sum to a single value, no need for a list:
for i,j in yearlyhours: model += pulp.lpSum([YAHL[i][j] + MAHL[i][j]]) == TEST[i][j]
Full Modified Code
Here's the complete fixed code for your test case:
from pulp import * import pandas as pd import numpy as np import xlrd model = pulp.LpProblem("Basic Model", pulp.LpMinimize) YPER = 5 HE = 6 yearlyhours = [(i,j) for i in range(YPER) for j in range(HE)] book = xlrd.open_workbook('Stack.xlsx') sheet11 = book.sheet_by_name('Sheet11') sheet12 = book.sheet_by_name('Sheet12') sheet13 = book.sheet_by_name('Sheet13') # Fixed: build row-first matrices TEST = [[sheet11.cell_value(i,j) for j in range(HE)] for i in range(YPER)] YAPR = [[sheet12.cell_value(i,j) for j in range(HE)] for i in range(YPER)] MAPR = [[sheet13.cell_value(i,j) for j in range(HE)] for i in range(YPER)] YAHL = pulp.LpVariable.dicts("YAHL", (range(YPER), range(HE)), lowBound=0, cat='Continuous') MAHL = pulp.LpVariable.dicts("MAHL", (range(YPER), range(HE)), lowBound=0, cat='Continuous') ##OBJECTIVE## model += pulp.lpSum([YAPR[i][j] * YAHL[i][j] + MAPR[i][j] * MAHL[i][j] for i in range(YPER) for j in range(HE)]), 'Sum_of_Value' # Fixed constraint indexing and simplified syntax for i,j in yearlyhours: model += pulp.lpSum([YAHL[i][j] + MAHL[i][j]]) == TEST[i][j] LpSolverDefault.msg = 1 model.writeLP('Opt.lp') model.solve() print("Status:", LpStatus[model.status]) obj = value(model.objective) print("Total Cost: ${:.2f}".format(obj)) print('\n')
Scaling to 365×24
This fix will work seamlessly for your 365×24 matrix—just update YPER = 365 and HE = 24, and the row-first matrix structure will align perfectly with your variables and constraints, no more index errors.
内容的提问来源于stack exchange,提问作者bathtub2007

