Python 中的容量最大覆盖位置生成

问题描述

我正在构建最大覆盖位置模型的变体,并希望限制每个“设施”可以覆盖的点数。我正在使用 Gurobi 优化。我曾尝试使用 AddConstr() 函数但失败了。每个 K 代表一个设施,r 代表半径。我的目标是添加一个约束来限制该半径内的点数。点是 x-y 坐标的二维数组。 K是输入的设施数量,M是总点数。我可以在这函数中完成这个还是需要添加一个变量?

import numpy as np
from scipy.spatial import distance_matrix
from gurobipy import *
from scipy.spatial import ConvexHull
from shapely.geometry import polygon,Point
from numpy import random

def generate_candidate_sites(points,M=100):
    hull = ConvexHull(points)
    polygon_points = points[hull.vertices]
    poly = polygon(polygon_points)
    min_x,min_y,max_x,max_y = poly.bounds
    sites = []
    while len(sites) < M:
        random_point = Point([random.uniform(min_x,max_x),random.uniform(min_y,max_y)])
        if (random_point.within(poly)):
            sites.append(random_point)
    return np.array([(p.x,p.y) for p in sites])

def mclp(points,K,radius,M):
    print('----- Configurations -----')
    print('  Number of points %g' % points.shape[0])
    print('  K %g' % K)
    print('  Radius %g' % radius)
    print('  M %g' % M)
    import time
    start = time.time()
    sites = generate_candidate_sites(points,M)
    J = sites.shape[0]
    I = points.shape[0]
    D = distance_matrix(points,sites)
    mask1 = D<=radius
    D[mask1]=1
    D[~mask1]=0
    # Build model
    m = Model()
    # Add variables
    x = {}
    y = {}
    for i in range(I):
      y[i] = m.addVar(vtype=GRB.BINARY,name="y%d" % i)
    for j in range(J):
      x[j] = m.addVar(vtype=GRB.BINARY,name="x%d" % j)

    m.update()
    # Add constraints
    m.addConstr(quicksum(x[j] for j in range(J)) == K)

    for i in range(I):
        m.addConstr(quicksum(x[j] for j in np.where(D[i]==1)[0]) >= y[i])

    m.setobjective(quicksum(y[i]for i in range(I)),GRB.MAXIMIZE)
    m.setParam('OutputFlag',0)
    m.optimize()
    end = time.time()
    print('----- Output -----')
    print('  Running time : %s seconds' % float(end-start))
    print('  Optimal coverage points: %g' % m.objVal)
    
    solution = []
    if m.status == GRB.Status.OPTIMAL:
        for v in m.getvars():
            # print v.varName,v.x
            if v.x==1 and v.varName[0]=="x":
               solution.append(int(v.varName[1:]))
    opt_sites = sites[solution]
    return opt_sites,m.objVal

def plot_input(points):
    from matplotlib import pyplot as plt
    fig = plt.figure(figsize=(8,8))
    plt.scatter(points[:,0],points[:,1],c='C0')
    ax = plt.gca()
    ax.axis('equal')
    ax.tick_params(axis='both',left=False,top=False,right=False,bottom=False,labelleft=False,labeltop=False,labelright=False,labelbottom=False)

def plot_result(points,opt_sites,radius):
    from matplotlib import pyplot as plt
    fig = plt.figure(figsize=(8,c='C0')
    ax = plt.gca()
    plt.scatter(opt_sites[:,opt_sites[:,c='C1',marker='+')
    for site in opt_sites:
        circle = plt.Circle(site,color='C1',fill=False,lw=2)
        ax.add_artist(circle)
    ax.axis('equal')
    ax.tick_params(axis='both',labelbottom=False)

运行一个小示例程序

import numpy as np
Npoints = 300
from sklearn.datasets import make_moons
points,_ = make_moons(Npoints,noise=0.15)
K = 20
radius = 0.2
M = 100
opt_sites,f = mclp(points,M)
plot_result(points,radius)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)