Python 一种算法,用于根据组中的人与谁兼容来匹配他们

Python 一种算法,用于根据组中的人与谁兼容来匹配他们,python,algorithm,matching,Python,Algorithm,Matching,我试图在一组人中根据他们的兼容性找到最大匹配。当我意识到我没有两个不同的组时,我正朝着二部图上的最大基数匹配前进 我现在的位置: 我有他们的ID列表:[1,8,3,15,13,21] 我有一个名为verify的函数,它将验证2个id是否兼容(可能有一个奇数) 然后,我创建每个人员索引与之兼容的索引图(字典): ids = [1, 8, 3, 15, 13, 21] l = len(ids) matches = {} for x in range(l):

我试图在一组人中根据他们的兼容性找到最大匹配。当我意识到我没有两个不同的组时,我正朝着二部图上的最大基数匹配前进

我现在的位置:

我有他们的ID列表:
[1,8,3,15,13,21]

我有一个名为verify的函数,它将验证2个id是否兼容(可能有一个奇数)

然后,我创建每个人员索引与之兼容的索引图(字典):

    ids = [1, 8, 3, 15, 13, 21]
    l = len(ids)
    matches = {}
    for x in range(l):
        matches.setdefault(x,[])
        for y in range(l):
            if x != y:
                if verify(ids[x],ids[y]):
                    matches[x].append(y)
这将产生:

{0: [3, 4, 5], 1: [2, 4, 5], 2: [1, 5], 3: [0, 4, 5], 4: [0, 1, 3], 5: [0, 1, 2, 3]}
现在我不确定从这里走到哪里,或者我是否应该走另一个方向


有人能给我指一下正确的方向吗?谢谢

看起来您正在尝试解决问题。我写了一个用Python和其他语言编写的解决方案。

在我看来,如果你想在一个图中找到所有节点都相互兼容(连接)的最大子集,那么你就是在寻找图中的最大团。据我所知,这是一个np完全问题,但也许我把你的问题搞错了。

我编写了一些适合你的例子的代码:

从输入导入列表,Dict,可选,Tuple
compat={0:[3,4,5],1:[2,4,5],2:[1,5],3:[0,4,5],4:[0,1,3],5:[0,1,2,3]}
def匹配(compat:Dict[int,List[int]])->可选[List[Tuple[int,int]]:
“”“匹配兼容的人。”“”
c=已排序(compat.items())
匹配:Dict[int,int]={}
m=_匹配(c,匹配)
如果m:
m={tuple(已排序([k,v]),用于m.items()中的k,v)
m=已排序(m)
返回m
def_匹配(c,匹配):
“”“以递归方式匹配兼容的人员。”“”
如果不是c:
回报匹配
个人,同胞=c[0]
如果匹配的人:
返回匹配(c[1:],匹配)
其他:
对于comp in compat:
如果不匹配:
匹配的[人]=公司
匹配的[comp]=人
如果匹配(c[1],匹配):
回报匹配
其他:
删除匹配的[个人],匹配的[公司]
一无所获
打印(匹配(compat))#[(0,3)、(1,4)、(2,5)]

以下是解决我的代码的逻辑(没有花时间将我的代码转换为SO版本):

答案如下:

给定我发布的邻接矩阵(基本上是一组边,但为什么要转换):

{0:[3,4,5],1:[2,4,5],2:[1,5],3:[0,4,5],4:[0,1,3],5:[0,1,2,3]}

最小的顶点是
2:[1,5]
,因此您可以取2,1点并删除该顶点

然后删除2,1的所有版本。(如果是顶点,则将其全部删除)

这就给您留下了:

{0:[3,4,5],3:[0,4,5],4:[0,3],5:[0,3]}
这是1个匹配项

重复逻辑(4,0),得到:这是匹配2

{3:[5],5:[3]}

最后重复一遍,你就得到了第三场比赛

我假设这是基于一个算法,但我不知道是哪一个

这比我的第一个解决方案要快得多。我的第一个解决方案是创建匹配的所有选项,然后查看哪个版本是最大的
感谢

此算法尝试使用迭代方法从输入中选取最大对,通常在随机数据的更详尽搜索模式的一对内,但运行时间很短

compats=[{0:[3,4,5],1:[2,4,5],2:[1,5],3:[0,4,5],4:[0,1,3],5:[0,1,2,3]},
{0: [4, 1], 1: [4, 0], 2: [4], 3: [4], 4: [0, 1, 2, 3]}]
def_检查(兼容):
“”“检查兼容性是相互的。”“”
compat2={k:set(v)for k,v在compat.items()中
对于p0,comp in compat2.items():
对于公司中的p1:
在compat2[p1]中断言p0\
f“{p0}与{p1}兼容,但{p1}与{p0}不兼容?”
每项=集合()
对于compat2.values()中的v:
每项|=v
差异=设置(兼容)。对称差异(每个项目)
assert not diffs,f“compat内部列表项!=compat键:{diffs}”
def most_matched2(compat:Dict[int,List[int]])->可选[List[Tuple[int,int]]:
“”“很可能,匹配大多数兼容的人。”“”
def重新排序(c_list:list[Tuple[Any,list[Any]]])->list[Tuple[Any,Any]]:
"""
重新排序兼容性;大多数兼容性首先是它们各自的兼容性
先排序最不相容的。
(重新排序([(0[4,1]),(1[4,0]),(2[4]),(3[4]),(4[0,1,2,3]))
== [(4, [3, 2, 1, 0]), (0, [1, 4]), (1, [0, 4]), (2, [4]), (3, [4])] )
"""
#首先对最多数量的兼容文件进行排序
c_list.sort(key=lambda x:(-len(x[1]),x))
#首先排序最不兼容的兼容项
顺序=[x[0]表示c_列表中的x]
对于个人,c_列表中的公司:
#打印(个人、公司)
组件排序(键=λx:-订单索引(x))
返回c_列表
c=[(k,list(v))表示compat.items()中的k,v
matches=set()
而c:
c=重新订购(c)
p0,p1=c[0][0],c[0][1][0]
add(元组(排序((p0,p1)))
p0p1_集={p0,p1}
c=[(p,剩余)表示p,c中的comp
如果p不在p0p1_集合中且(保持:=列表(集合(comp)-p0p1_集合))]
返回排序(匹配项)
对于同胞中的同胞:
_支票(兼容)
打印(最匹配2(兼容))
打印()
#%%测试生成
从itertools导入组合
来自随机导入样本,randint
从集合导入defaultdict
自始至终都是单调的
作为pd进口熊猫
def测试发电机(n,k):
可能性=列表(组合中c的集合(c)(范围(n),2))
如果{int,float}中的类型(k):
k=int(最小(k,len(可能)))
成对=[]
而len(pairs)