コード例 #1
0
def set_testl(market_instances_list, airport_list, market_data,
              segment_travel_time, time_zone_dict, iti_dict, fleet_data,
              passeger_type_dict, attr_value, marketpt_attr_sum, solver):
    """
    很多输入变量都是字典,就是为了在模型中生成子集的时候有筛选功能 即 if dict【m】 in dict 
    :param airport_list: 
    :param market_data: 
    :param segment_travel_time: 
    :param iti_dict:itinerary number key ,info value :{0: {'market': "M('SEA', 'LAX')", 'non_stop': ('SEA', 'LAX'), ('SEA', 'LAX'): 1, 'legs': [('SEA', 'LAX')]}
    :param fleet_data: 
    :param passeger_type_dict: passenger_type as key , and it's proportions
    :param attr_value: 
    :param marketpt_attr_sum: 
    :param solver: 
    :return: time_table, q_variable for each itinerary, 
    """
    market_iti = {}  #market:itinerary list
    for m in market_instances_list:
        l = [
            i for i, v in iti_dict.items()
            if v['market'] == 'M' + str(m.od_pair)
        ]
        market_iti.update({m: l})
    model = ConcreteModel()
    market = list(market_data.keys())  #['M' + str(m.od_pair) for m in ]
    # market_segment={m:[(market_data[m][4],market_data[m][5])] for m in market_data.keys()}
    model.M = Set(initialize=market, doc='Player Market_obj')
    model.Mi = Set(list(market_iti.keys()),
                   initialize=market_iti,
                   doc='Player Market_obj')
    model.AP = Set(initialize=airport_list)
    model.Segment = Set(initialize=((i, j) for i in model.AP for j in model.AP
                                    if i != j))

    # create time spot [1-72] and it's time
    a = np.linspace(1, int((1440 - 360) / 15), int((1440 - 360) / 15))
    time_list = np.arange(360, 1440, 15)
    time_dict = dict(zip(a, time_list))
    # reverse_time_dict = {v: k for k, v in time_dict.items()}
    model.T = Set(
        initialize=a,
        ordered=True,
        doc='Time period from 300 min to 1440 ,step :15min,number:73')
    model.I = Set(initialize=iti_dict.keys(), doc='itinerary _index,size 4334')
    model.Im = Set(initialize=((m, i) for m in model.M for i in market_iti[m]),
                   doc='tuple(m,i),size 4334')  # 筛选出只在m的itinerary 的 号码
    model.PT = Set(initialize=passeger_type_dict.keys())
    model.F = Set(initialize=fleet_data.keys())
    d = {}  #create a dict as which OD and time get all itinerary_index in it
    for ap1, ap2 in model.Segment:
        for t in model.T:
            v = []
            for i, va in iti_dict.items():
                if (ap1, ap2) in va['legs'] and t == va[(ap1, ap2)]:
                    v.append(i)
            d[(ap1, ap2, t)] = v
    model.St = Set(
        list(d.keys()),
        initialize=d)  # index as (ap1,ap2,time) get [itinerary index list]

    def _filter3(model, i, m, ap1, ap2, t):

        return i in model.Mi[m].value and i in model.St[(ap1, ap2, t)].value

    # def Parameters
    demand_pt = {
    }  # get demand of pt in the market by total demand times its proportion
    print("passenger_type_proportion:", passeger_type_dict)
    for m, va in market_data.items():
        for ty, rato in passeger_type_dict.items():
            demand_pt.update({(m, ty):
                              va[0] * rato})  # market demand times proportions
    model.Dem = Param(model.M,
                      model.PT,
                      initialize=demand_pt,
                      doc='Market demand for each type of passenger')

    price_dict = {}
    for i in model.I:
        rato = np.linspace(1.3, 0.7, len(passeger_type_dict))
        for index, ty in enumerate(passeger_type_dict):
            if iti_dict[i]['non_stop']:
                price_dict.update({
                    (i, ty):
                    market_data[iti_dict[i]['market']][2] * rato[index]
                })  # market_data[m][2] is price
            else:
                price_dict.update({
                    (i, ty):
                    0.8 * market_data[iti_dict[i]['market']][2] * rato[index]
                })  # market_data[m][2] is price
    model.p = Param(model.I, model.PT, initialize=price_dict)
    model.Avail = Param(
        model.F,
        initialize={fleet: value[0]
                    for fleet, value in fleet_data.items()})
    model.Cap = Param(
        model.F,
        initialize={fleet: value[1]
                    for fleet, value in fleet_data.items()})
    model.distance = Param(model.Segment,
                           initialize={(value[-2], value[-1]): value[1]
                                       for value in market_data.values()})

    def ope_cost(model, ap1, ap2, f):
        if model.distance[ap1, ap2] <= 3106:
            return (1.6 * model.distance[ap1, ap2] + 722) * (model.Cap[f] +
                                                             104) * 0.019
        else:
            return (1.6 * model.distance[ap1, ap2] + 2200) * (model.Cap[f] +
                                                              211) * 0.0115

    model.Ope = Param(model.Segment, model.F, initialize=ope_cost, doc='cost')
    freq = {(market_data[m][4], market_data[m][5]): market_data[m][3]
            for m in market_data.keys()}

    model.Freq = Param(model.Segment, initialize=freq)
    model.A = Param(model.I, model.PT, initialize=attr_value)

    model.Am = Param(model.M, model.PT, initialize=marketpt_attr_sum)
    # Step 2: Define decision variables
    model.x = Var(model.Segment, model.F, model.T, within=Binary)
    model.y_1 = Var(model.F, model.AP, model.T, within=PositiveIntegers)
    model.y_2 = Var(model.F, model.AP, model.T, within=PositiveIntegers)
    model.q = Var(model.I, model.PT, within=NonNegativeReals)
    model.non_q = Var(model.M, model.PT, within=NonNegativeReals
                      )  # number of pax that choose others airine and no fly.

    # Step 3: Define Objective
    def obj_rule(model):
        return sum(model.q[i, pt] * model.p[i, pt] for i in model.I
                   for pt in model.PT) - sum(model.Ope[s, f] * model.x[s, f, t]
                                             for s in model.Segment
                                             for f in model.F for t in model.T)

    model.obj = Objective(rule=obj_rule, sense=maximize)

    def obj_cost(model):
        return sum(model.Ope[s, f] * model.x[s, f, t] for s in model.Segment
                   for f in model.F for t in model.T)

    model.obj_cost = Expression(rule=obj_cost)

    def obj_revenue(model):
        return sum(model.q[i, pt] * model.p[i, pt] for i in model.I
                   for pt in model.PT)

    model.obj_revenue = Expression(rule=obj_revenue)

    # add constraint
    # Aircraft count:
    def aircraft_con(model, f):
        return sum(model.y_1[f, ap, model.T[1]]
                   for ap in model.AP) <= model.Avail[f]

    model.count = Constraint(model.F, rule=aircraft_con)

    # flow balance cons
    def flow_balance_1(model, f, ap):
        return model.y_1[f, ap, model.T[1]] == model.y_2[f, ap, model.T[-1]]

    model.con_fb_1 = Constraint(model.F, model.AP, rule=flow_balance_1)

    def flow_balance_2(model, f, ap, t):
        # if t == model.T[-1]:
        #     return Constraint.Skip
        # else:
        return model.y_1[f, ap, t + 1] == model.y_2[f, ap, t]

    def filter2(model, t):
        return t != model.T[-1]

    model.Tm = Set(initialize=(i for i in model.T if i != model.T[-1]))
    #model.con_fb_2 = Constraint(model.F, model.AP, model.T, rule=flow_balance_2)
    model.con_fb_2 = Constraint(model.F,
                                model.AP,
                                model.Tm,
                                rule=flow_balance_2)
    # time_zone_dict={('ANC', 'PDX'): 60, ('SEA', 'PDX'): 0, ('SEA', 'ANC'): -60, ('ANC', 'LAX'): 60, ('PDX', 'SEA'): 0, ('LAX', 'PDX'): 0,
    #                 ('LAX', 'SEA'): 0, ('PDX', 'ANC'): -60, ('SEA', 'LAX'): 0, ('ANC', 'SEA'): 60, ('LAX', 'ANC'): -60, ('PDX', 'LAX'): 0}

    Travel_time = segment_travel_time

    def flow_balance_3(model, f, ap, t):
        def D(s, t, turnaround=30):
            arrival_time = time_dict[t]
            dep_time = arrival_time - (Travel_time[s] +
                                       turnaround) - time_zone_dict[s]
            if dep_time >= 360:
                t0 = ((dep_time - 360) // 15) + 1
            else:
                t0 = 72 - (abs(360 - dep_time) // 15)
            return t0

        return model.y_1[f, ap, t] + sum(
            model.x[s, f, D(s, t)]
            for s in model.Segment if s[1] == ap) == model.y_2[f, ap, t] + sum(
                model.x[s, f, t] for s in model.Segment if s[0] == ap)

    model.con_fb_3 = Constraint(model.F,
                                model.AP,
                                model.T,
                                rule=flow_balance_3)

    # Demand and capacity constrains:
    def attract_con(model, market, i, pt):
        return model.Am[market, pt] * (
            model.q[i, pt] / model.Dem[market, pt]) <= model.A[i, pt] * (
                model.non_q[market, pt] / model.Dem[market, pt])

    model.attractiveness = Constraint(model.Im, model.PT, rule=attract_con)

    def capacity_con(model, ap1, ap2, t):
        return sum(model.q[i, pt] for i in d[(ap1, ap2, t)]
                   for pt in model.PT) <= sum(
                       model.Cap[f] * model.x[ap1, ap2, f, t] for f in model.F)

    model.con_d1 = Constraint(model.Segment, model.T, rule=capacity_con)

    def demand_market_con(model, market, pt):
        return sum(model.q[i, pt] for i in model.I if iti_dict[i]['market'] == market) + model.non_q[market, pt] == \
               model.Dem[market, pt]

    model.con_d3 = Constraint(model.M, model.PT, rule=demand_market_con)

    # Itinerary selection constraints:
    model.AC = Set(initialize=model.I * model.M * model.Segment * model.T,
                   filter=_filter3)

    def iti_selection(model, i, m, ap1, ap2, t, pt):
        # if i in market_iti[m] and i in d[(ap1, ap2, t)]:
        return sum(model.x[ap1, ap2, f, t]
                   for f in model.F) >= model.q[i, pt] / model.Dem[m, pt]

    model.con_iti_selection = Constraint(model.AC,
                                         model.PT,
                                         rule=iti_selection)

    # Restrictions on fight leg variables:
    def flight_leg_con(model, ap1, ap2, t):
        return sum(model.x[ap1, ap2, f, t] for f in model.F) <= 1

    model.con_leg_1 = Constraint(model.Segment, model.T, rule=flight_leg_con)

    def freq_con(model, ap1, ap2):
        return sum(model.x[ap1, ap2, f, t] for t in model.T
                   for f in model.F) == model.Freq[ap1, ap2]

    model.con_let_2 = Constraint(model.Segment, rule=freq_con)
    print("____" * 5)
    # for con in model.component_map(Constraint).itervalues():
    #     con.pprint()

    SOLVER_NAME = solver
    TIME_LIMIT = 60 * 60 * 2
    results = SolverFactory(SOLVER_NAME)

    if SOLVER_NAME == 'cplex':
        results.options['timelimit'] = TIME_LIMIT
    elif SOLVER_NAME == 'glpk':
        results.options['tmlim'] = TIME_LIMIT
    elif SOLVER_NAME == 'gurobi':
        results.options['TimeLimit'] = TIME_LIMIT

    com = results.solve(model, tee=True)
    com.write()

    #absgap = com.solution(0).gap
    # get x results in matrix form
    df_x = pd.DataFrame(columns=list(model.Segment), index=model.T)
    for s in model.Segment:
        for t in model.T:
            for f in model.F:
                if model.x[s, f, t].value > 0:
                    df_x.loc[t, [s]] = f

    #df_x=df_x.reset_index()# return value  is a dataframe of new time table
    # 所有的决策变量都遍历一遍
    # for v in instance.component_objects(Var, active=True):
    #     print("Variable", v)
    #     varobject = getattr(instance, str(v))
    #     for index in varobject:
    #         print("   ", index, varobject[index].value)
    varobject = getattr(model, 'q')
    q_data = {(i, pt): varobject[(i, pt)].value
              for (i, pt), v in varobject.items() if varobject[(i, pt)] != 0}
    df_q = pd.DataFrame.from_dict(q_data,
                                  orient="index",
                                  columns=["variable value"])
    varobject2 = getattr(model, 'non_q')
    nonq_data = {(m, pt): varobject2[(m, pt)].value
                 for (m, pt), v in varobject2.items()
                 if varobject2[(m, pt)] != 0}

    # q = list(model.q.get_values().values())
    # print('q = ', q)
    profit = model.obj()
    print('\nProfit = ', profit)
    cost = value_s(model.obj_cost())
    #revenue=value_s(model.obj_revenue())
    print('cost is:' * 10, cost)
    #print('revenue is:' * 10, revenue)
    '''
    print('\nDecision Variables')
    #list_of_vars = [v.value for v in model.component_objects(ctype=Var, active=True, descend_into=True)]
    #var_names = [v.name for v in model.component_objects(ctype=Var, active=True, descend_into=True) if v.value!=0]

    # print("y=",y)
    model.obj.display()

    def pyomo_postprocess( options=None, instance=None, results=None ):
        model.x.display()

    pyomo_postprocess(None, model, results)
    for v in model.component_objects(Var, active=True):
        print("Variable component object", v)
        varobject = getattr(model, str(v))
        for index in varobject:
            if varobject[index].value != 0:
                print("   ", index, varobject[index].value)
    '''
    return df_x, q_data, profit, cost, nonq_data