Ошибка nlopt неверного аргумента в add_inequality_mconstraint - PullRequest
0 голосов
/ 19 апреля 2020

Постановка проблемы: я пытаюсь использовать nlopt с интерфейсом python, чтобы минимизировать целевую функцию, которая минимизирует сумму евклидовых расстояний между взвешенными узлами неориентированного графа с взвешенными ребрами, когда они размещаются на сетке. Ограничения заключаются в том, что емкость любой ячейки сетки не нарушается. То есть сумма весов узлов в ячейке сетки не превышает ее емкости. При попытке добавить вектор ограничений неравенства с помощью opt.add_inequality_mconstraint появляется ошибка «nlopt invalid аргумент». Мои ограничения для каждой ячейки сетки, длина которой равна 6. Вот мой код:

import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import nlopt as nlo


# Problem data creation
# Given a set of nodes and weighted edges,
# place them on a grid of cells which have a link capacity,
# such that the number of nodes in a grid cell
# dont exceed a certain capacity

#E.g graph - 10 nodes with connectivity matrix
#6 grid cells arranged as 2x3
num_nodes = 10
#Weight of each node
nodeWts = np.array([16.,21.,15.,24.,4.,14.,31.,11.,12.,10.])
num_grid_cells = 6
#Capacity of each grid cell
gridCellCapacities = np.array([40.,40.,40.,40.,40.,40.])
gtol = np.array([2,2,2,2,2,2])
gridIds = np.arange(6)
splitGrid = np.split(gridIds,2)
splitGridR = splitGrid[::-1]
splitGridMtx = np.vstack(splitGridR)
gridMtx = gridIds.reshape(2,3)
print('gids: ', gridIds)
cellConnectivity = np.matrix([[0.,5.,2.,0.,0.,0.,0.,0.,0.,0.],
                              [5.,0.,0.,2.,0.,0.,0.,0.,0.,8.],
                              [2.,0.,0.,2.,3.,0.,5.,0.,0.,0.],
                              [0.,2.,2.,0.,2.,4.,0.,0.,0.,0.],
                              [0.,0.,3.,2.,0.,2.,3.,0.,0.,6.],
                              [0.,0.,0.,4.,2.,0.,0.,0.,0.,0.],
                              [0.,0.,5.,0.,3.,0.,0.,0.,3.,0.],
                              [0.,0.,0.,0.,0.,0.,0.,0.,2.,3.],
                              [0.,0.,0.,0.,0.,0.,3.,2.,0.,8.],
                              [0.,8.,0.,0.,6.,0.,0.,3.,8.,0.]])
ccr = cellConnectivity.reshape(num_nodes, num_nodes)
print('sg: ', splitGridR)
print('gmx: ', splitGridMtx)
X = np.zeros(num_nodes, order='C')
Y = np.zeros(num_nodes, order='C')
XY = np.hstack([X,Y])
XYLen = len(XY)
initialXY = np.array([0.5,0.5,1.5,1.5,0.5,1.5,0.5,1.5,1.5,2.5,0.5,0.5,0.5,0.5,1.5,1.5,1.5,1.5,1.5,0.5])

print('XY: ', XY)

def myobj(XY, grad):
    if (grad.size > 0):
        print('GRAD NOT YET IMPLEMENTED')
    result = 0.
    xr = 0.
    yr = 0.
    for i in range(num_nodes):
        for j in range(num_nodes):
            if (i != j):
                xr = np.square(XY[i]-XY[j])
                yr = np.square(XY[i+num_nodes] - XY[j+num_nodes])
                result += 0.5*(ccr[i,j])*(np.sqrt(xr+yr))
    return result

def myconstr(cresult, XY, grad):
    if (grad.size > 0):
        print('CONSTRAINT GRADIENT NOT IMPLEMENTED')
    gridWts = np.zeros(num_grid_cells)
    gridLoc = np.zeros(shape=(num_nodes,num_grid_cells))
    for i in range(num_nodes):
        for j in range(num_grid_cells):
            gridLoc[i,j] = np.ceil(XY[i]) + np.abs(np.square(np.ceil(XY[i+num_nodes]))) - 2
            loc = int(gridLoc[i,j])
            gridWts[loc] += nodeWts[i]
    for k in range(num_grid_cells):
        cresult[k] = gridWts[k] - gridCellCapacities[k]

opt = nlo.opt(nlo.LN_NELDERMEAD, XYLen)

lb = np.zeros(XYLen)
ub = np.zeros(XYLen)
for i in range(XYLen):
    if (i < num_nodes):
        lb[i] = 0.1
        ub[i] = 3.0
    else:
        lb[i] = 0.1
        ub[i] = 2.0
print('LB: ', lb)
print('UB: ', ub)
grad = np.array([])
cresult = np.zeros(num_grid_cells)
opt.set_lower_bounds(lb)
opt.set_upper_bounds(ub)
opt.set_min_objective(myobj)

opt.add_inequality_mconstraint(myconstr,gtol)
opt.set_initial_step(0.1)
opt.optimize(initialXY)
print('OPTIMAL WL: ', opt.last_optimum_value())
print('LOR: ', opt.last_optimize_result())
print('XY: ', XY)
...