You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在scipy.optimize.minimize函数中约束x为整数?

How to Enforce Integer Constraints for scipy.optimize.minimize

Hey there! The standard scipy.optimize.minimize tool is built for continuous optimization—it doesn't have native support for integer constraints, which is why you're getting decimal results even after setting value ranges. But there are a couple of reliable workarounds depending on your problem type:

1. Use scipy.optimize.milp (for Linear Problems)

If your objective function and constraints are linear, milp (Mixed Integer Linear Programming) is the most straightforward choice. It natively supports integer variable declarations.

Example Code:

import numpy as np
from scipy.optimize import milp, LinearConstraint

# Define your linear objective coefficients (e.g., minimize sum(x))
objective_coeffs = np.array([1, 1, 1, 1, 1])
# Set bounds for each variable: [0, 12] for all 5 variables
variable_bounds = [(0, 12) for _ in range(5)]
# Mark all variables as integers (1 = integer, 0 = continuous)
integrality_flags = [1] * 5

# Run the mixed integer linear optimization
result = milp(c=objective_coeffs, bounds=variable_bounds, integrality=integrality_flags)

# Print the integer solution
print("Integer solution:", result.x)

2. Use Heuristic Methods (for Non-Linear Problems)

If your objective function is non-linear, milp won't work. Instead, you can use a heuristic optimizer like scipy.optimize.basinhopping with a callback to enforce integer constraints at each iteration.

Example Code:

import numpy as np
from scipy.optimize import basinhopping, minimize

# Your non-linear objective function (customize this to your use case)
def non_linear_objective(x):
    return (x[0]-2)**2 + (x[1]-10)**2 + (x[2]-5)**2 + (x[3]-7)**2 + (x[4]-3)**2

# Callback function to clamp values to integers within [0,12]
def enforce_integer_constraint(x, f, accept):
    # Round to nearest integer and clip to stay within bounds
    x_int = np.round(x).astype(int)
    x_clamped = np.clip(x_int, 0, 12)
    # Update the current solution to the integer version
    x[:] = x_clamped
    return accept

# Initial guess (your original decimal result)
initial_guess = np.array([1.0, 11.1, 5.4, 6.9, 3.4])

# Run basinhopping with integer constraints
result = basinhopping(
    non_linear_objective,
    initial_guess,
    minimizer_kwargs={"bounds": [(0, 12)]*5},  # Keep values in range
    callback=enforce_integer_constraint,
    niter=100  # Adjust iterations based on your problem complexity
)

# Print the integer solution
print("Integer solution:", result.x)

Notes on Basinhopping:

  • It's a stochastic method, so you might need to tweak niter or other parameters to find a good solution.
  • For more complex non-linear integer problems, you could also explore third-party libraries like DEAP (genetic algorithms) or PuLP, but the above method works within the SciPy ecosystem.

3. Brute-Force Grid Search (Small Problem Sizes Only)

If you have a very small number of variables, you could brute-force all integer combinations within your bounds. But this becomes infeasible quickly as the number of variables grows (curse of dimensionality!).


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

火山引擎 最新活动