我在Python中使用nlopt,我在矩阵中获取一些值,在与其二维之和一样多的变量中定义一个函数,设置一些约束并进行优化。这帮助我找到最大化图熵表达式的参数。
基于这个矩阵添加可变数量的约束是很困难的,我不断收到“索引 0 超出范围”错误:
result[count] = vars[i] * vars[j] - 1 # vars[i] * vars[j] < 1
~~~~~~^^^^^^^
IndexError: index 0 is out of bounds for axis 0 with size 0
当我尝试添加约束时。从本质上讲,这种添加约束的方法有什么问题?
import numpy as np
import sympy as sp
import ast
import nlopt
Qgreen = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
len1, len2 = Qgreen.shape
# Calculate strength along the rows
strength1 = [np.sum(Qgreen[i, :]) for i in range(len1)]
# Calculate strength along the columns
strength2 = [np.sum(Qgreen[:, i]) for i in range(len2)]
# Combine the strengths into one list
str_combined = strength1 + strength2
# Define symbolic variables
vars = sp.symbols(f'x1:{len(str_combined)+1}') # x1, x2, ..., x6
# Create the function using symbolic expressions
f_sum = sum(s * sp.log(v) for s, v in zip(str_combined, vars))
# Flatten the product terms and their logarithms
product_terms = []
for i in range(len1):
for j in range(len1, len1 + len2):
product_terms.append(vars[i] * vars[j])
# Adding the log(1 - product_terms) part of the expression
f_product = sum(sp.log(1 - term) for term in product_terms)
# Final function combining both parts
f = f_sum + f_product
# Create a lambda function for fast evaluation
f_lambdified = sp.lambdify(vars, f, "numpy")
# Define the function for nlopt (minimization)
def nlopt_function(vars, grad):
if grad.size > 0:
# Compute the gradient if needed
grad[:] = np.array([sp.diff(f, var).evalf(subs={v: vars[i] for i, v in enumerate(vars)}) for i, var in enumerate(vars)])
return f_lambdified(*vars)
def constraints(vars, result):
count = 0
num_vars = len(vars) # Total number of variables
print(num_vars)
for i in range(num_vars):
for j in range(num_vars):
if i != j: # Avoid self-products
result[count] = vars[i] * vars[j] - 1 # The constraints are vars[i] * vars[j] < 1
count += 1
opt = nlopt.opt(nlopt.LN_COBYLA, len(vars)) # Use COBYLA which supports constraints
opt.set_max_objective(nlopt_function)
opt.add_inequality_constraint(constraints, 1e-8)
initial_guess = np.random.uniform(0, 1, len(vars))
optimized_vars = opt.optimize(initial_guess)
max_val = opt.last_optimum_value()
print("Optimized variables:", optimized_vars)
print("Maximum value:", max_val)
我正在尝试添加约束的各种组合,但不断出现相同的索引越界错误。
有几件事:
dd_inequality_mconstraint
而不是 dd_inequality_constraint
我做了一个更简单的例子,尽管在我的例子中它都是线性的,但非线性问题的语法是相同的。
from numpy import eye
from nlopt import opt, LN_COBYLA
def objective(x, grad):
if grad.size:
grad[:] = 1
return sum(x)
def constraints(results, x, grad):
if grad.size:
grad[:, :] = eye(3)
results[:] = x - [2, 3, 4]
def main():
opti = opt(LN_COBYLA, 3)
opti.set_max_objective(objective)
opti.add_inequality_mconstraint(constraints, [1e-8] * 3)
opti.set_ftol_abs(1e-4)
optimized_vars = opti.optimize([1] * 3)
max_val = opti.last_optimum_value()
print("Optimized variables:", optimized_vars)
print("Maximum value:", max_val)
if __name__ == '__main__':
main()
在这里,我只是在
x[0] + x[1] + x[2]
、x[0] < 2
和 x[1] < 3
约束下最大化总和 x[2] < 3
。显然,解决方案是[2, 3, 4]
:
Optimized variables: [2.00000882 3.00001096 4.00001634]
Maximum value: 9.000036118453766