Python 实现最小成本流算法或有条件分组分配

Python 实现最小成本流算法或有条件分组分配,python,optimization,graph,or-tools,network-flow,Python,Optimization,Graph,Or Tools,Network Flow,我试图根据参与者的偏好将他们分配到组Tn和子组TnSm。我正在使用最小成本流方法,使用Python中Google的OR工具。考虑下面的偏好表: T1S1 T1S2 T1S3 T2S1 T2S2 T2S3 name1 1 0 3 2 2 3 name2 2 1 1 1 0 1 name3 0 2 1 2 2

我试图根据参与者的偏好将他们分配到组
Tn
和子组
TnSm
。我正在使用最小成本流方法,使用Python中Google的OR工具。考虑下面的偏好表:

      T1S1  T1S2    T1S3    T2S1    T2S2    T2S3
name1 1     0       3       2       2       3
name2 2     1       1       1       0       1
name3 0     2       1       2       2       3
name4 3     2       3       3       0       0
name5 1     0       2       3       1       2
...
两组
Tn
共有6个斑点,由3个亚组
TnSm
组成,每个亚组有2个斑点。我有以下几个条件:

  • 参与者总数小于或等于所有小组名额之和(=12)
  • 每个参与者可以是1-3个小组的一部分,但前提是这些小组是同一小组的一部分
  • 这12个团体名额各分配一名参加者
  • 我可以将参与者分配到几个子组,方法是为每个参与者在源位置创建一个容量为3的节点,为每个子组在接收器位置创建一个容量为2的节点:

    容量=[3,3,3,…]+[1,1,1,1…]+[2,2,2,2,2,2]

    但是,如果某个特定的子组是组
    Tn
    的一部分,我现在如何确保只将参与者分配到第二或第三个子组

    if min_cost_flow_2.SolveMaxFlowWithMinCost() == min_cost_flow_2.OPTIMAL:
        print('Minimum cost:', min_cost_flow_2.OptimalCost(), min_cost_flow_2.MaximumFlow())
        for arc in range(min_cost_flow_2.NumArcs()):
            if min_cost_flow_2.Tail(arc) != source and min_cost_flow_2.Head(arc) != sink:
                if min_cost_flow_2.Flow(arc) > 0:
                    print(" ")
                    print("***worker %d assigned to team %d at cost: %d" % (min_cost_flow_2.Tail(arc),min_cost_flow_2.Head(arc),min_cost_flow_2.UnitCost(arc)))
    

    这是我的又快又脏的建议。
    注意:我添加了约束

    • 参与者不能同时使用子组的两个点
    #/usr/bin/env蟒蛇3
    从ortools.sat.python导入cp_模型
    def main():
    参与者=[
    “名称1”,
    “名称2”,
    “名称3”,
    “名称4”,
    “名称5”,
    “名称6”,
    “姓名7”,
    “名称8”,
    #“名称9”,
    #“姓名10”,
    #“名称11”,
    #“姓名12”,
    ]
    首选项=[
    #T0 T0 T0 T0 T0 T0 T1 T1 T1
    #S0 S0 S1 S1 S2 S2 S0 S0 S1 S1 S2 S2
    #a b a b a b a b a b a b b
    [1, 1, 0, 0, 3, 3, 2, 2, 2, 2, 3, 3],  # 1
    [2, 2, 3, 3, 1, 1, 1, 1, 0, 0, 1, 1],  # 2
    [0, 0, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3],  # 3
    [3, 3, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0],  # 4
    [1, 1, 0, 0, 2, 2, 3, 3, 1, 1, 2, 2],  # 5
    [1, 1, 0, 0, 3, 3, 2, 2, 3, 3, 2, 2],  # 6
    [2, 2, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],  # 7
    [0, 0, 2, 2, 1, 1, 2, 2, 2, 2, 3, 3],  # 8
    [3, 3, 1, 1, 0, 0, 3, 3, 0, 0, 2, 2],  # 9
    [1, 1, 0, 0, 2, 2, 3, 3, 0, 0, 2, 2],  # 10
    [1, 1, 0, 0, 3, 3, 2, 2, 2, 2, 3, 3],  # 11
    [2, 2, 1, 1, 0, 0, 3, 3, 2, 2, 1, 1],  # 12
    ]
    num_参与者=len(参与者)
    所有参与者=范围(参与者数量)
    组数=2
    所有组=范围(数量组)
    num_sub_group=3
    所有子组=范围(数量子组)
    num_sub_groups_spots=2
    所有子组点=范围(数量子组点)
    #每个TxSy 2个点
    #创建模型
    model=cp_model.CpModel()
    #变数
    #如果参与者被分配到此位置,则为True
    x={}
    对于所有参与者中的p:
    对于所有组中的tn:
    对于所有子组中的sg:
    对于所有子组中的sg:
    x[(p,tn,sg,sg_s)]=模型新布尔值(
    f“x[{参与者[p]},{tn},{sg},{sg_}]”)
    #如果参与者被分配到此组,则为True
    y={}
    对于所有参与者中的p:
    对于所有组的tn:
    y[(p,tn)]=model.NewBoolVar(f“y[{participants[p]},{tn}]))
    #约束条件
    #每个点只分配给一名参与者。
    对于所有组中的tn:
    对于所有子组中的sg:
    对于所有子组中的sg:
    模型。添加(
    所有参与者中n的总和(x[(n,tn,sg,sg)]=1)
    #每个参与者不能同时使用任何组的任何子组的两个点。
    对于所有参与者中的p:
    对于所有组中的tn:
    对于所有子组中的sg:
    模型。添加(
    所有子组中n的总和(x[(p,tn,sg,n)]=1)
    模型。添加(
    所有子组中n的总和(x[(p,tn,n,m)]
    对于所有子组中的m(点)>=1)。仅限强制(
    y[(p,tn)])
    #执行非y[(p,tn)]==(和(x[(p,tn,*,*)])==0)
    模型。添加(
    所有子组中n的总和(x[(p,tn,n,m)]
    对于所有子组中的m(点)==0)。仅限强制(
    y[(p,tn)]。不是()
    #模型。最小化(
    模型。最大化(
    总数([
    x[(p,tn,sg,sg_s)]*偏好[p][tn*sg*sg_s+sg*sg_s]
    对于所有参与者中的p
    对于所有组中的tn
    对于所有子组中的sg
    对于所有子组中的sg
    ]))
    #创建解算器并求解。
    solver=cp_model.CpSolver()
    状态=求解器。求解(模型)
    如果状态==cp_model.OPTIMAL:
    打印('Maximum cost=%i'%solver.ObjectiveValue())
    打印()
    对于所有参与者中的p:
    对于所有组中的tn:
    对于所有子组中的sg:
    对于所有子组中的sg:
    如果解算器值(x[(p,tn,sg,sg_s)]==1:
    印刷品(
    f'Participant:{participants[p]},分配给T{tn}S{sg}:{sg_S},偏好({preferences[p][tn*sg*sg_S+sg*sg_S+sg_S]})
    )
    #统计数字。
    打印()
    打印('统计')
    打印('-冲突:%i'%solver.NumConflicts())
    打印('-分支:%i'%solver.NumBranches())
    打印('-wall时间:%f“%s”%solver.WallTime()
    如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
    main()
    
    解决方案:

    /assignment.py
    最高成本=27
    参与者:姓名1,分配给T0S0:1,首选项(1)
    参与者:姓名2,分配给T0S1:1,首选项(3)
    参与者:姓名3,分配到T1S1:1,首选项(2)
    参与者:姓名4,分配到T1S0:0,首选项(3)
    参与者:姓名4,分配到T1S1:0,首选项(3)
    参与者:姓名4,分配