如何用SymPy同时求解包含方程与不等式的非线性方程组?
Hey there! Let's tackle this KKT system problem you're facing— I remember hitting similar roadblocks when I was new to SymPy and optimization, so I get exactly where you're coming from.
First, let's clarify what's going on: your kunSys is a typical Karush-Kuhn-Tucker (KKT) system, mixing equality constraints, complementary slackness conditions (the product terms like w1*x1), and non-negativity inequalities for the Lagrange multipliers. SymPy's default solve() function struggles with this mix because it doesn't handle multi-variable inequalities well, which is why you're seeing that NotImplementedError.
The Fix: Case-Based Enumeration (Leveraging Complementary Slackness)
The key here is that complementary slackness terms (like w0*(-x1 -2*x2 +2) = 0) mean either the first factor is zero, or the second factor is zero (or both). We can enumerate all possible combinations of these cases, solve each smaller system, then filter out solutions that don't satisfy the non-negativity constraints.
Let's walk through this with code:
Step 1: Set Up SymPy and Define Your System
from sympy import symbols, Eq, solve, And # Define variables x1, x2, w0, w1, w2 = symbols('x1 x2 w0 w1 w2') # Define equality constraints eq1 = Eq(-w0 + w1 - 8*x1 + 20, 0) eq2 = Eq(-2*w0 + w2 - 8*x2 + 4, 0) eq3 = Eq(w0*(-x1 - 2*x2 + 2), 0) eq4 = Eq(w1*x1, 0) eq5 = Eq(w2*x2, 0) # Define non-negativity inequalities non_neg = And(w0 >= 0, w1 >= 0, w2 >= 0)
Step 2: Enumerate Complementary Slackness Cases
We have three complementary slackness terms, each giving two possibilities. That's 2^3 = 8 total cases to check:
- Case 1:
w0 = 0,w1 = 0,w2 = 0 - Case 2:
w0 = 0,w1 = 0,x2 = 0 - Case 3:
w0 = 0,x1 = 0,w2 = 0 - Case 4:
w0 = 0,x1 = 0,x2 = 0 - Case 5:
-x1 -2*x2 +2 = 0,w1 = 0,w2 = 0 - Case 6:
-x1 -2*x2 +2 = 0,w1 = 0,x2 = 0 - Case 7:
-x1 -2*x2 +2 = 0,x1 = 0,w2 = 0 - Case 8:
-x1 -2*x2 +2 = 0,x1 = 0,x2 = 0
Step 3: Solve Each Case and Filter Valid Solutions
Let's automate this process with code:
# List all complementary slackness cases cases = [ (Eq(w0, 0), Eq(w1, 0), Eq(w2, 0)), (Eq(w0, 0), Eq(w1, 0), Eq(x2, 0)), (Eq(w0, 0), Eq(x1, 0), Eq(w2, 0)), (Eq(w0, 0), Eq(x1, 0), Eq(x2, 0)), (Eq(-x1 - 2*x2 + 2, 0), Eq(w1, 0), Eq(w2, 0)), (Eq(-x1 - 2*x2 + 2, 0), Eq(w1, 0), Eq(x2, 0)), (Eq(-x1 - 2*x2 + 2, 0), Eq(x1, 0), Eq(w2, 0)), (Eq(-x1 - 2*x2 + 2, 0), Eq(x1, 0), Eq(x2, 0)), ] valid_solutions = [] for case in cases: # Combine case conditions with equality constraints system = [eq1, eq2, *case] # Solve the equality system solutions = solve(system, (x1, x2, w0, w1, w2), dict=True) # Filter solutions that meet non-negativity rules for sol in solutions: if non_neg.subs(sol): valid_solutions.append(sol) # Print valid results print("Valid KKT solutions:") for sol in valid_solutions: print(sol)
What You'll Get
When you run this code, you'll get valid solutions that satisfy all your system's requirements. For example, one valid solution is:
{x1: 2, x2: 0, w0: 4, w1: 0, w2: 4}
This solution checks all boxes: all equations hold, and w0, w1, w2 are non-negative.
Why This Works
By breaking down the problem into smaller, equality-only systems, we avoid SymPy's limitations with multi-variable inequalities. Each case is easy for SymPy to solve, and we just filter out invalid solutions afterward to keep only those that meet the non-negativity constraints.
内容的提问来源于stack exchange,提问作者oo00oo00oo00

