排序点算法

Sorting points algorithm

简要说明我想做什么:
假设我们有 14 个数据点,每个数据点的随机坐标在 (-10, -10) 和 (10, 10) 之间,并且它们被分配了一种颜色——红色或蓝色。我希望能够形成必须满足 4 个条件的最多 7 个点的簇:
一个指定集群中可以包含的红色数据点的最大数量,一个指定集群中的最大点数,另一个指定集群中点的最大数量,另一个表示它们的位置必须靠近 - 即我们不能在簇内有 2 个点 (-10, -10) 和 (10, 10).

老实说,我什至不知道从哪里开始,我尝试使用 k-means 排序将数据点组织成簇,但这不满足最大红点数约束。

这里有一些示例 Python 使用 OR-Tools 帮助您入门。

import collections
import math
import random

from ortools.linear_solver import pywraplp


Point = collections.namedtuple("Point", ["x", "y", "is_red"])


def random_point():
    return Point(random.uniform(-10, 10), random.uniform(-10, 10), random.randrange(2))


def close_enough(p, q):
    return math.hypot(p.x - q.x, p.y - q.y) <= 5


def assign(points, max_clusters, max_overall, max_red):
    solver = pywraplp.Solver.CreateSolver("SCIP")
    variables = {
        (i, j): solver.BoolVar("")
        for i in range(len(points))
        for j in range(max_clusters)
    }
    for i in range(len(points)):
        solver.Add(sum(variables[i, j] for j in range(max_clusters)) == 1)
    for i1, p1 in enumerate(points):
        for i2, p2 in enumerate(points):
            if not close_enough(p1, p2):
                for j in range(max_clusters):
                    solver.Add(variables[i1, j] + variables[i2, j] <= 1)
    for j in range(max_clusters):
        solver.Add(sum(variables[i, j] for (i, p) in enumerate(points)) <= max_overall)
    for j in range(max_clusters):
        solver.Add(
            sum(variables[i, j] for (i, p) in enumerate(points) if p.is_red) <= max_red
        )
    status = solver.Solve()
    if status == pywraplp.Solver.OPTIMAL:
        groups = [[] for j in range(max_clusters)]
        for i, p in enumerate(points):
            for j in range(max_clusters):
                if variables[i, j].SolutionValue():
                    groups[j].append(p)
        return groups


if __name__ == "__main__":
    print(assign([random_point() for i in range(14)], 7, 7, 3))