是什么导致我的脚本在计算机上失败,但在另一台计算机上运行正常?

时间:2019-04-25 15:31:44

标签: python-2.7 version networkx pyomo

我正在运行用于网络流量优化的脚本,并且正在与另一个人进行协作。我正在使用networkx建立模型并将其馈送到pyomo。我的脚本未运行,并且未构建模型。报告的唯一错误是

  

ValueError:未初始化的NumericValue对象build_pipe [_s1_3,s]没有值

其中build_pipe[_s1_3,s]是具有在csv文件中定义的参数的边,该文件肯定定义了所有需要的输入。尽管此错误使我的脚本无法运行,但其他人也可以运行该脚本。在python 2.7上使用networkX 2.1和pyomo 5.6.1。

我们比较了软件包版本,它们是相同的。我能想到的唯一区别是,他在Spyder上运行脚本,而我在jupyter笔记本上运行我的脚本。过去曾出现此错误,但是一些编辑(用#**标记)解决了该错误。不知道这次要更改什么。

def create_graph(nodefile, arcfile):
    g = networkx.DiGraph()
    # read the data files
    # We assume the first column of the node file is the node name
    # We also assume the arc file's first two columns are (node start, node end)
    nodes = pandas.read_csv(nodefile)
    arcs = pandas.read_csv(arcfile)
    # create the nodes and associated data
    nameCol = nodes.columns[0]
    for num,arow in nodes.iterrows():
        g.add_node( arow[nameCol], **(dict(arow))) 
    # create the arcs and associated data
    firstNodeCol = arcs.columns[0]
    secondNodeCol = arcs.columns[1]
    for num,arow in arcs.iterrows():
        g.add_edge( arow[firstNodeCol], arow[secondNodeCol], **(dict(arow))) 
    return g

def create_pyomo_network_lp_primal(g,cost_field='Cost',capacity_field='Capacity',node_imbalance_field='SupplyDemand', interdiction_field='xbar'):
    # Create the model
    model = pe.ConcreteModel()
    # Tell pyomo to read in dual-variable information from the solver
    model.dual = pe.Suffix(direction=pe.Suffix.IMPORT)

    # Associate the graph with this model
    model.g = g

    # Create the problem data
    model.node_set = pe.Set( initialize=g.nodes() )
    model.edge_set = pe.Set( initialize=g.edges(), dimen=None) #**added ", dimen=None"

    model.edge_cost = pe.Param( model.edge_set, 
            initialize=lambda model, i,j: model.g.adj[i][j].get(cost_field,0))
    model.edge_capacity = pe.Param( model.edge_set, 
            initialize=lambda model, i,j: model.g.adj[i][j].get(capacity_field,0))
    model.node_imbalance = pe.Param( model.node_set, 
            initialize=lambda model, i: model.g.node[i].get(node_imbalance_field,0))
    model.edge_delay_on = pe.Param( model.edge_set, 
            initialize=lambda model, i,j: model.g.adj[i][j].get(interdiction_field,0), mutable=True)

    # Compute nCmax
    nCmax = model.g.number_of_nodes() * max([data.get(cost_field, 0) for e0,e1,data in model.g.edges(data=True) ])
    model.nCmax = nCmax
    model.delay = pe.Param(initialize= 2*nCmax + 1, mutable=True)

    # Create the variables
    model.y = pe.Var(model.edge_set, domain=pe.NonNegativeReals) #flow across each edge
    model.build_pipe = pe.Var(model.edge_set, domain=pe.Binary) #binary whether we build a pipe for each edge #**added model.build_pipe which is a binary decision variable on whether or not the model chooses to build a pipe along a specific edge. Initialize it at 1 so that the model will solve (i.e. all pipes start with a 1, meaning that all pipes are initially built, then the model removes pipes to improve the objective)

    model.UnsatSupply = pe.Var(model.node_set, domain=pe.NonNegativeReals)
    model.UnsatDemand = pe.Var(model.node_set, domain=pe.NonNegativeReals)

    # Create the objective
    def obj_rule(model):
        return  pe.summation(model.edge_cost, model.build_pipe) + model.delay * pe.summation(model.edge_delay_on, model.y) + model.nCmax * pe.summation(model.UnsatDemand) #**removed " + model.nCmax * pe.summation(model.UnsatSupply)" which adds a penalty to the objective if not all of the supply is used. Updated the first OBJ term to use "model.build_pipe" instead of "model.y", which means that the objective depends on what piping network we build, not on the amount of flow we send over the pipes

    model.OBJ = pe.Objective(rule=obj_rule, sense=pe.minimize)


    # Create the constraints, one for each node
    def flow_bal_rule(model, n):
        expr = 0
        if model.g.in_edges(n):
            expr += pe.summation(model.y, index=model.g.in_edges(n))
        if model.g.out_edges(n):
            expr += - pe.summation(model.y, index=model.g.out_edges(n))
        supply_node = (model.node_imbalance[n] < 0)
        demand_node = (model.node_imbalance[n] > 0)
        constr = (expr == model.node_imbalance[n] + model.UnsatSupply[n]*int(supply_node) - model.UnsatDemand[n]*int(demand_node) )
        if isinstance(constr, bool):
            if constr == True:
                return pe.Constraint.Feasible
            return pe.Constraint.Infeasible
        return constr

    model.FlowBalance = pe.Constraint(model.node_set, rule=flow_bal_rule)


    # Create the capacity constraints, one for each edge
    def capacity_rule(model, i, j):
        return model.y[(i,j)] <= model.edge_capacity[(i,j)] * model.build_pipe[(i,j)] #** added " * model.build_pipe[(i,j)]" which means that the capacity of an edge is zero unless we choose to build it (if we choose to build pipe(i,j), then model.build_pipe[(i,j)] will equal 1, otherwise it equals 0)

    model.Capacity = pe.Constraint(model.edge_set, rule=capacity_rule)


    # Solve the model
    #model.create()#** WARNING: DEPRECATION WARNING: the Model.create() method is deprecated.  Call Model.create_instance() to create a concrete instance from an abstract model.  You do not need to call Model.create() for a concrete model.
    model= resolve_mip(model)

    # Print the model objective
    print 'Primal objective function value:', model.OBJ()
    return model

# ============================================================================
# This is a useful function, in case you want to re-solve a model in the
# interpreter.  Remember that if you dynamically want to change model
# parameters, you have to declare them as 'mutable' in the model.  If you look
# above, we've declared edge_delay_on and delay as mutable in this case.
# ============================================================================

def resolve_mip(model, tee=False):
    model.preprocess()
    solver = pyomo.opt.SolverFactory('cplex')
    results = solver.solve(model, tee=tee, keepfiles=False) #** removed " , options="mip_tolerances_integrality=1e-9 mip_tolerances_mipgap=0") "

    # Check that we actually computed an optimal solution, load results
    if (results.solver.status != pyomo.opt.SolverStatus.ok):
        logging.warning('Check solver not ok?')
    if (results.solver.termination_condition != pyomo.opt.TerminationCondition.optimal):  
        logging.warning('Check solver optimality?')

    #model.load(results) #** WARNING: DEPRECATION WARNING: the Model.load() method is deprecated for loading solutions stored in SolverResults objects.  By default, results from solvers are immediately loaded into the original model instance.

    model.g.OBJ_val = model.OBJ()

    # Load solution data back into the networkx object 
    if hasattr(model, 'y'):
        for e in model.edge_set:
            model.g.adj[e[0]][e[1]]['flow_val'] = model.y[e].value
            model.g.adj[e[0]][e[1]]['build_pipe'] = model.build_pipe[e].value #**added build_pipe to the model output solution

    #if hasattr(model, 'dual'): #** remove the following 3 lines. I'm not sure what this code snippet does, but it was throwing errors. I think it has to do with running the interdiction version of the model.
     #   for n in model.FlowBalance.iterkeys(): 
      #      model.g.node[n]['dual_val'] = model.dual[ model.FlowBalance[n] ]

    if hasattr(model, 'x'):
        for e in model.edge_set:
            model.g.adj[e[0]][e[1]]['attackActive'] = model.x[e].value

    if hasattr(model, 'UnsatDemand'):
        for n in model.node_set:
            model.g.node[n]['UnsatDemand'] = model.UnsatDemand[n].value
            model.g.node[n]['UnsatSupply'] = model.UnsatSupply[n].value

    return model

# ============================================================================
# Here, we are printing a nice report on the solution to the screen.  You have
# to pass a networkx object, with the flow_val field loaded.
# ============================================================================

def print_solution(g):

    edges = sorted(g.edges(data=True))
    for e0,e1,data in edges:
        if data.has_key('attackActive') and data['attackActive'] == 1:
            print 'Interdict arc %s -> %s'%(str(e0), str(e1))
    print

    nodes = sorted(g.nodes(data=True))
    for n,data in nodes:
        if data.has_key('UnsatSupply') and data['UnsatSupply'] > 0:
            print 'Remaining supply on node %s: %.2f'%(str(n), data['UnsatSupply'])
    for n,data in nodes:
        if data.has_key('UnsatDemand') and data['UnsatDemand'] > 0:
            print 'Remaining demand on node %s: %.2f'%(str(n), data['UnsatDemand'])
    print

    for e0,e1,data in edges:
        if data.has_key('flow_val') and data['flow_val'] > 0:
            print 'Flow on arc %s -> %s: %.2f'%(str(e0), str(e1), data['flow_val'])
    print

    #** added the following printout
    print "Pipes Built:"
    for e0,e1,data in edges:
        if data.has_key('build_pipe') and data['build_pipe'] > 0 and len(e0) > 3:
            print '   %s: %s-inch'%(str(e0), str(e0)[-1])
    print

    print '----------'
    print 'Total cost = ', g.OBJ_val 


# ===============================================================
# Now that we've defined all our functions, lets do something....
#
# First, lets read the data. 
# ===============================================================

g = create_graph('nodes_multi_pipe.csv', 'edges_multi_pipe.csv')

# ===============================================================
# Lets solve and print the flow when there are no
# interdictions.
# ===============================================================

mPrimal = create_pyomo_network_lp_primal(g, capacity_field='Capacity')

print 'Flow without interdictions:'
print_solution(mPrimal.g)

0 个答案:

没有答案