Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用多进程在Python中构建Gurobi表达式_Python_Multithreading_Python 3.x_Gurobi - Fatal编程技术网

使用多进程在Python中构建Gurobi表达式

使用多进程在Python中构建Gurobi表达式,python,multithreading,python-3.x,gurobi,Python,Multithreading,Python 3.x,Gurobi,首先,我正在使用jupyter笔记本,python版本3.5,Gurobi 7.0.2及其python接口,所有这些都在Red Hat上 这就是我问题的背景:我想解决一个二次问题,它有大量的变量。建立目标函数需要1-2个多小时 我曾考虑过使用NumPy GPU加速,但表达式有点复杂,因此,这不是一个解决方案 因此,我尝试使用几个线程来构建目标函数。然而,我得到了一个错误,我不知道如何处理它 我简化了我的代码,因此它更具可读性(错误仍然相同) 首先,Gurobi优化器不支持多线程进行模型构建。即使

首先,我正在使用jupyter笔记本,python版本3.5,Gurobi 7.0.2及其python接口,所有这些都在Red Hat上

这就是我问题的背景:我想解决一个二次问题,它有大量的变量。建立目标函数需要1-2个多小时

我曾考虑过使用NumPy GPU加速,但表达式有点复杂,因此,这不是一个解决方案

因此,我尝试使用几个线程来构建目标函数。然而,我得到了一个错误,我不知道如何处理它

我简化了我的代码,因此它更具可读性(错误仍然相同)


首先,Gurobi优化器不支持多线程进行模型构建。即使我们这样做了,在正确编写的应用程序中,模型构建几乎从来都不是瓶颈

在本例中,有许多表达式看起来像x+x+x。虽然正确,但这是非常低效的——写3*x要好得多。下面是惩罚函数的快速重写:

# var is an array of GRB.BINARY
# D=edge_costs
def penalty_function(var,obj,D):
    num_nodes = len(var)
    for i,fil in enumerate(D):
        for j,val in enumerate(fil):
            # -x*D*x
            if val!=0:
                obj+=var[i]*var[j]*val
            # -x(i)x(j)*min(Ds)
            if(j>i):
                minval = sum(min(D[j][k],D[i][k]) for k in range(num_nodes))
                if minval != 0:
                    obj += var[i]*var[j]*minval
    return obj
对于埃尔文·卡维拉根提出的问题,一个快速的解决办法是

编辑:通过组合两个var[i]*var[j]术语,我们可以使惩罚函数稍微更有效:

def penalty_function(var,obj,D):
    num_nodes = len(var)
    for i,fil in enumerate(D):
        for j,val in enumerate(fil):
            # -x(i)x(j)*min(Ds)
            if(j>i):
                val += sum(min(D[j][k],D[i][k]) for k in range(num_nodes))
            # -x*D*x
            if val!=0:
                obj += var[i]*var[j]*val
    return obj

在添加GregGlockner改进后,我意识到我可以以不同的方式使用numpy和多线程。我把它加在这里,以防有人对它感兴趣

def parallel_function(D,num_nodes,start,end):     
    minD=[]
    if(end>num_nodes-1):
        end=num_nodes
    for i in range(start,end,1):
        # fill with 0 (triangular matrix)
        minval=[0]*(i+1)
        for j,val in enumerate(D[i]):
            if(j>i):
                minval.append(sum(min(D[j][k],D[i][k]) for k in range(num_nodes)))
        minD.append(minval)
    return minD

def penalty_function(var,obj,D,num_nodes):
    num_process=8
    inc=math.ceil(num_nodes/num_process)
    if __name__ == '__main__':
        pool = mp.Pool(processes=num_process)              # start 8 worker processes
        minval=pool.starmap(parallel_function, [(D,num_nodes,u*inc,u*inc+inc) for u in range(8)])
        pool.close()
    minD=[]
    for x in minval:
        minD=minD+x
    obj+=np.array(var).dot((np.array(minD)+np.array(D))).dot(var)
    return obj

更多信息会有所帮助。有多少个变量?对于目标函数,线性项中有多少个非零,二次项中有多少个非零?计算机上的内存和处理器是什么?是的,我使用的是Intel(R)Core(TM)i7 CPU 870@2.93GHz和16GB内存。一个简化的问题是:优化一个有1行、414列和414个非零的模型模型有4257个二次目标项变量类型:0个连续变量、414个整数(414个二进制变量),顺便说一句,我不是在寻找最优解。我想这个问题很难解决。到目前为止,我已经设置了一个超时,我对古洛比给我的结果感到满意。我的问题是在优化之前,当我在构建目标函数时。但是,我将添加更多关于目标函数的信息。请注意,两个二进制变量的乘法可以很容易地线性化。这里不需要使用二次项。我如何建模?可能是这样的?:x*y等于z,有两个约束z≤x和z≤设置PreQLinearize参数非常有效。由于你回答的第一部分,我将把这个问题设置为已解决。非常感谢你!
# var is an array of GRB.BINARY
# D=edge_costs
def penalty_function(var,obj,D):
    num_nodes = len(var)
    for i,fil in enumerate(D):
        for j,val in enumerate(fil):
            # -x*D*x
            if val!=0:
                obj+=var[i]*var[j]*val
            # -x(i)x(j)*min(Ds)
            if(j>i):
                minval = sum(min(D[j][k],D[i][k]) for k in range(num_nodes))
                if minval != 0:
                    obj += var[i]*var[j]*minval
    return obj
def penalty_function(var,obj,D):
    num_nodes = len(var)
    for i,fil in enumerate(D):
        for j,val in enumerate(fil):
            # -x(i)x(j)*min(Ds)
            if(j>i):
                val += sum(min(D[j][k],D[i][k]) for k in range(num_nodes))
            # -x*D*x
            if val!=0:
                obj += var[i]*var[j]*val
    return obj
def parallel_function(D,num_nodes,start,end):     
    minD=[]
    if(end>num_nodes-1):
        end=num_nodes
    for i in range(start,end,1):
        # fill with 0 (triangular matrix)
        minval=[0]*(i+1)
        for j,val in enumerate(D[i]):
            if(j>i):
                minval.append(sum(min(D[j][k],D[i][k]) for k in range(num_nodes)))
        minD.append(minval)
    return minD

def penalty_function(var,obj,D,num_nodes):
    num_process=8
    inc=math.ceil(num_nodes/num_process)
    if __name__ == '__main__':
        pool = mp.Pool(processes=num_process)              # start 8 worker processes
        minval=pool.starmap(parallel_function, [(D,num_nodes,u*inc,u*inc+inc) for u in range(8)])
        pool.close()
    minD=[]
    for x in minval:
        minD=minD+x
    obj+=np.array(var).dot((np.array(minD)+np.array(D))).dot(var)
    return obj