Scipy约束最小化未遵守等式约束问题咨询
Let's cut to the chase: the L-BFGS-B optimizer in SciPy ignores your equality constraint entirely. Here's why, and how to fix it:
The Root Cause
L-BFGS-B is built exclusively for optimization problems with only bound constraints (like your 0 ≤ q_i ≤ 1 limits). It has no support for equality or inequality constraints—any constraints parameter you pass to it will be silently ignored. That’s exactly why your solution’s elements don’t sum to 1: the constraint was never applied in the first place.
Fix 1: Switch to an Optimizer That Supports Constraints
The simplest, most reliable fix is to use SciPy's SLSQP method, which natively handles both equality and bound constraints. Here’s how to adjust your code:
import numpy as np from scipy.optimize import minimize def EV(q, P): return (-1)*np.sum(100 * q * (2*P - 1)) # Replace with your actual P and initial guess X0 P = np.random.rand(12) # Example given 12D array X0 = np.ones(12) / 12 # Initial uniform distribution (sum=1) # Define constraints and bounds cons = {'type': 'eq', 'fun': lambda q: np.sum(q) - 1} bds = [(0, 1)] * 12 # Use SLSQP instead of L-BFGS-B result = minimize( EV, X0, args=(P,), method='SLSQP', bounds=bds, constraints=cons, tol=1e-8 # Optional: tighten tolerance for stricter constraint satisfaction ) # Verify the solution print(f"Sum of optimized q: {np.sum(result.x):.8f}") print(f"Optimization success: {result.success}")
SLSQP will enforce your sum-to-1 rule while respecting the 0-1 bounds on each element. For most use cases, this is the best approach.
Fix 2: Reparameterize Variables to Eliminate the Equality Constraint
If you specifically need to use L-BFGS-B (e.g., for performance with large-scale problems), you can reparameterize your variables to embed the sum-to-1 constraint directly into the objective function. Since sum(q) = 1, you only need 11 independent variables—derive the 12th as q_12 = 1 - sum(q_1 ... q_11).
For a cleaner fit with L-BFGS-B, use a softmax transformation to automatically enforce the probability simplex (sum=1, all elements ≥0):
import numpy as np from scipy.optimize import minimize def EV_softmax(z, P): # Convert unconstrained z values to valid q via softmax q = np.exp(z) / np.sum(np.exp(z)) return (-1)*np.sum(100 * q * (2*P - 1)) # Example inputs P = np.random.rand(12) X0_softmax = np.zeros(12) # Simple initial guess # Use L-BFGS-B with loose bounds for z (softmax handles the simplex) result = minimize( EV_softmax, X0_softmax, args=(P,), method='L-BFGS-B', bounds=[(-10, 10)]*12 ) # Convert back to the original q variable q_opt = np.exp(result.x) / np.sum(np.exp(result.x)) print(f"Sum of optimized q: {np.sum(q_opt):.8f}")
The softmax transformation ensures q automatically meets the sum-to-1 and non-negativity rules, so you don’t need any constraints at all—perfect for L-BFGS-B’s bound-only design.
Key Takeaways
- L-BFGS-B does not support equality/inequality constraints—only use it for problems with variable bounds.
- For constrained problems,
SLSQPis the standard go-to method in SciPy. - If you must use L-BFGS-B, reparameterize variables to embed constraints into the objective function (like softmax for simplex rules).
内容的提问来源于stack exchange,提问作者Davide Floriello

