1. 程式人生 > >deap實戰_2017中國數學建模大賽_B題_第二題

deap實戰_2017中國數學建模大賽_B題_第二題

簡介

補充:本例子僅僅是之前deap類庫的一個實戰例子,所以先別問我數學建模的事情,我暫時不想回答(還有為毛踩我文章…..我本來就不是寫數學建模的……╮(╯▽╰)╭)(2017/10/31)

原問題是給出一個定價策略,證明其相較於原來定價策略的優點.

那麼首先我們第一題第二問得到了一個 價格-完成率 函式,此時我們需要的是給出一個新的定價函式,並利用遺傳演算法得到最佳引數.

思路

  1. 編碼–>我們需要編碼的是定價函式的引數
  2. 評價函式—->將編碼輸入的定價函式得到價格,然後將價格輸入之前得到的 價格-完成率 函式得到完成率
  3. 求解的目標應當是最大化完成率
  4. 為了控制成本需要對價格進行一定的限制,避免為了提高完成率,而過高定價

Types

import random

from deap import base
from deap import creator
from deap import tools

import time

ThresholdValue = 28.6670026583

creator.create("FitnessMax", base.Fitness, weights=(1.0,))  # 定義最大化適應度
creator.create("Individual", list, fitness=creator.FitnessMax)  # 這裡的list種群的資料型別

toolbox = base.Toolbox
() # Attribute generator: define 'attr_bool' to be an attribute ('gene') # which corresponds to integers sampled uniformly # from the range [0,1] (i.e. 0 or 1 with equal # probability) toolbox.register("attr_bool", random.random) # 包含了0,1的隨機整數,初始化種群
# Structure initializers: define 'individual' to be an individual # consisting of 100 'attr_bool' elements ('genes') toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox.attr_bool, 5) # define the population to be a list of 'individual's toolbox.register("population", tools.initRepeat, list, toolbox.individual)

ReadData

讀取資料,為之後的計算做準備


import pandas as pd

df2 = pd.read_csv('/home/fonttian/Data/MM2017/db.csv')

npones = df2['npones']
level = df2['level']
length = df2['length']
MiDu = df2['MiDu']
npjt = df2['npjt']
listlen = df2['listlen']
price = df2['price']

定義評價函式(適應度函式)


def evalOneMax(individual):
    newPrice = (individual[0] - 0.5) * npones * 20 + (individual[1] - 0.5) * length * 20 + (individual[2] - 0.5) * MiDu * 20 + (individual[3] - 0.5) * level * 20 + (individual[4]) * 100 +listlen * 65.7
    # npones,nplength,npMiDuList3
    w2 = [-0.01633732, 0.83539635, -0.06544261, -0.00280863]
    xjb = length * w2[0] + level * w2[1] + MiDu * w2[2] + npjt * w2[3]
    xjb = xjb * newPrice
    sums = 0
    for i in range(len(xjb)):
        # yuzhi = 28.6670026583
        # if xjb[i] >= yuzhi and newPrice[i] <= price[i] *1.1: # 608
        # if xjb[i] >= yuzhi: # 655
        # yuzhi = 0.474373718686

        if xjb[i] >= ThresholdValue and sum(newPrice) <= 57707.5 * 1.3: # 655
            sums += 1
        else:
            pass

    return sums, # 注意最後的 , 該檔案中必須要有,不然會報錯

註冊其他引數(Operator registration)

# ---------------------Operator registration---------------------
toolbox.register("evaluate", evalOneMax)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)

設計執行程式,獲取我們想要的結果

def main():
    random.seed(64)
    # hash(64)is used

    # random.seed方法的作用是給隨機數物件一個種子值,用於產生隨機序列。
    # 對於同一個種子值的輸入,之後產生的隨機數序列也一樣。
    # 通常是把時間秒數等變化值作為種子值,達到每次執行產生的隨機系列都不一樣

    # create an initial population of 300 individuals (where
    # each individual is a list of integers)
    pop = toolbox.population(n=300)  # 定義300個個體的種群

    # CXPB  is the probability with which two individuals
    #       are crossed
    #
    # MUTPB is the probability for mutating an individual
    #
    # NGEN  is the number of generations for which the
    #       evolution runs   迭代次數
    CXPB, MUTPB, NGEN = 0.5, 0.2, 100

    print("Start of evolution")

    # Evaluate the entire population
    fitnesses = list(map(toolbox.evaluate, pop))
    # for ind, fit in zip(pop, fitnesses):
    #     ind.fitness.values = fit

    print("  Evaluated %i individuals" % len(pop))  # 這時候,pop的長度還是300呢
    print("  迭代 %i 次" % NGEN)

    t1 = time.clock()
    # Begin the evolution      開始進化了哈!!!注意注意注意!就是一個for迴圈裡了!NGEN次--代數
    for g in range(NGEN):
        if g % 10 == 0:
            print("-- Generation %i --" % g)

        # Select the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        # Clone the selected individuals
        offspring = list(map(toolbox.clone, offspring))

        # Apply crossover and mutation on the offspring
        for child1, child2 in zip(offspring[::2], offspring[1::2]):

            # cross two individuals with probability CXPB
            if random.random() < CXPB:
                toolbox.mate(child1, child2)

                # fitness values of the children
                # must be recalculated later
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:

            # mutate an individual with probability MUTPB
            if random.random() < MUTPB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # print("  Evaluated %i individuals" % len(invalid_ind))

        # The population is entirely replaced by the offspring
        pop[:] = offspring

        # Gather all the fitnesses in one list and print the stats
        fits = [ind.fitness.values[0] for ind in pop]

        length = len(pop)
        mean = sum(fits) / length
        sum2 = sum(x * x for x in fits)
        std = abs(sum2 / length - mean ** 2) ** 0.5

        # print("  Min %s" % min(fits))
        # print("  Max %s" % max(fits))
        # print("  Avg %s" % mean)
        # print("  Std %s" % std)

    print("-- End of (successful) evolution --")

    best_ind = tools.selBest(pop, 1)[0]
    print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

    print('預測資料')
    # PevalOneMax([0.6222847026584997, 0.9952779203368345, 0.10901692485431957, 0.8966275594961192, 0.9692993203252058])
    print('該次遺傳演算法的出的最好的引數的通過數:')
    PevalOneMax(best_ind)

    print('出題方給的定價規律的預測通過數',TevalOneMax())
    t2 = time.clock()
    print(t2 - t1)

全部程式碼

# - * - coding: utf - 8 -*-
# 作者:田豐(FontTian)
# 建立時間:'2017/9/17'
#    This file is part of DEAP.
#
#    DEAP is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as
#    published by the Free Software Foundation, either version 3 of
#    the License, or (at your option) any later version.
#
#    DEAP is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with DEAP. If not, see <http://www.gnu.org/licenses/>.


#    example which maximizes the sum of a list of integers
#    each of which can be 0 or 1

import random

from deap import base
from deap import creator
from deap import tools

import time

ThresholdValue = 28.6670026583

creator.create("FitnessMax", base.Fitness, weights=(1.0,))  # 定義最大化適應度
creator.create("Individual", list, fitness=creator.FitnessMax)  # 這裡的list種群的資料型別

toolbox = base.Toolbox()

# Attribute generator: define 'attr_bool' to be an attribute ('gene')
#                      which corresponds to integers sampled uniformly
#                      from the range [0,1] (i.e. 0 or 1 with equal
#                      probability)


toolbox.register("attr_bool", random.random)  # 包含了0,1的隨機整數,初始化種群

# Structure initializers: define 'individual' to be an individual
#                         consisting of 100 'attr_bool' elements ('genes')
toolbox.register("individual", tools.initRepeat, creator.Individual,
                 toolbox.attr_bool, 5)

# define the population to be a list of 'individual's
toolbox.register("population", tools.initRepeat, list, toolbox.individual)

import pandas as pd

df2 = pd.read_csv('/home/fonttian/Data/MM2017/db.csv')

npones = df2['npones']
level = df2['level']
length = df2['length']
MiDu = df2['MiDu']
npjt = df2['npjt']
listlen = df2['listlen']
price = df2['price']


def evalOneMax(individual):
    newPrice = (individual[0] - 0.5) * npones * 20 + (individual[1] - 0.5) * length * 20 + (individual[2] - 0.5) * MiDu * 20 + (individual[3] - 0.5) * level * 20 + (individual[4]) * 100 +listlen * 65.7
    # npones,nplength,npMiDuList3
    w2 = [-0.01633732, 0.83539635, -0.06544261, -0.00280863]
    xjb = length * w2[0] + level * w2[1] + MiDu * w2[2] + npjt * w2[3]
    xjb = xjb * newPrice
    sums = 0
    for i in range(len(xjb)):
        # yuzhi = 28.6670026583
        # if xjb[i] >= yuzhi and newPrice[i] <= price[i] *1.1: # 608
        # if xjb[i] >= yuzhi: # 655
        # yuzhi = 0.474373718686

        if xjb[i] >= ThresholdValue and sum(newPrice) <= 57707.5 * 1.3: # 655
            sums += 1
        else:
            pass

    return sums,

def PevalOneMax(individual):
    print((individual[0] - 0.5) * 20, (individual[1] - 0.5) * 20, (individual[2] - 0.5) * 20, (individual[3] - 0.5) * 20, (individual[4]) * 100)
    newPrice = (individual[0] - 0.5) * npones * 20 + (individual[1] - 0.5) * length * 20 + (individual[2] - 0.5) * MiDu * 20 + (individual[3] - 0.5) * level * 20 + (individual[4]) * 100
    w2 = [-0.01633732, 0.83539635, -0.06544261, -0.00280863]
    xjb = length * w2[0] + level * w2[1] + MiDu * w2[2] + npjt * w2[3]
    xjb = xjb * newPrice
    sums = 0
    for i in range(len(xjb)):
        if xjb[i] >= ThresholdValue:
            sums += 1
        else:
            pass

    print(sums)
    print("新的總價:",sum(newPrice),'舊的總價:',sum(price))

    return sums,

# ---------------------Operator registration---------------------
toolbox.register("evaluate", evalOneMax)
toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
toolbox.register("select", tools.selTournament, tournsize=3)


def TevalOneMax():
    # 原定價模型的通過率
    w2 = [-0.01633732, 0.83539635, -0.06544261, -0.00280863]
    xjb = length * w2[0] + level * w2[1] + MiDu * w2[2] + npjt * w2[3]
    xjb = xjb * price
    sum = 0
    for i in range(len(xjb)):
        if xjb[i] >= ThresholdValue:
            sum += 1
        else:
            pass
    return sum

# --------------------- main ---------------------

def main():
    random.seed(64)
    # hash(64)is used

    # random.seed方法的作用是給隨機數物件一個種子值,用於產生隨機序列。
    # 對於同一個種子值的輸入,之後產生的隨機數序列也一樣。
    # 通常是把時間秒數等變化值作為種子值,達到每次執行產生的隨機系列都不一樣

    # create an initial population of 300 individuals (where
    # each individual is a list of integers)
    pop = toolbox.population(n=300)  # 定義300個個體的種群

    # CXPB  is the probability with which two individuals
    #       are crossed
    #
    # MUTPB is the probability for mutating an individual
    #
    # NGEN  is the number of generations for which the
    #       evolution runs   迭代次數
    CXPB, MUTPB, NGEN = 0.5, 0.2, 100

    print("Start of evolution")

    # Evaluate the entire population
    fitnesses = list(map(toolbox.evaluate, pop))
    # for ind, fit in zip(pop, fitnesses):
    #     ind.fitness.values = fit

    print("  Evaluated %i individuals" % len(pop))  # 這時候,pop的長度還是300呢
    print("  迭代 %i 次" % NGEN)

    t1 = time.clock()
    # Begin the evolution      開始進化了哈!!!注意注意注意!就是一個for迴圈裡了!NGEN次--代數
    for g in range(NGEN):
        if g % 10 == 0:
            print("-- Generation %i --" % g)

        # Select the next generation individuals
        offspring = toolbox.select(pop, len(pop))
        # Clone the selected individuals
        offspring = list(map(toolbox.clone, offspring))

        # Apply crossover and mutation on the offspring
        for child1, child2 in zip(offspring[::2], offspring[1::2]):

            # cross two individuals with probability CXPB
            if random.random() < CXPB:
                toolbox.mate(child1, child2)

                # fitness values of the children
                # must be recalculated later
                del child1.fitness.values
                del child2.fitness.values

        for mutant in offspring:

            # mutate an individual with probability MUTPB
            if random.random() < MUTPB:
                toolbox.mutate(mutant)
                del mutant.fitness.values

        # Evaluate the individuals with an invalid fitness
        invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
        fitnesses = map(toolbox.evaluate, invalid_ind)
        for ind, fit in zip(invalid_ind, fitnesses):
            ind.fitness.values = fit

        # print("  Evaluated %i individuals" % len(invalid_ind))

        # The population is entirely replaced by the offspring
        pop[:] = offspring

        # Gather all the fitnesses in one list and print the stats
        fits = [ind.fitness.values[0] for ind in pop]

        length = len(pop)
        mean = sum(fits) / length
        sum2 = sum(x * x for x in fits)
        std = abs(sum2 / length - mean ** 2) ** 0.5

        # print("  Min %s" % min(fits))
        # print("  Max %s" % max(fits))
        # print("  Avg %s" % mean)
        # print("  Std %s" % std)

    print("-- End of (successful) evolution --")

    best_ind = tools.selBest(pop, 1)[0]
    print("Best individual is %s, %s" % (best_ind, best_ind.fitness.values))

    print('預測資料')
    # PevalOneMax([0.6222847026584997, 0.9952779203368345, 0.10901692485431957, 0.8966275594961192, 0.9692993203252058])
    print('該次遺傳演算法的出的最好的引數的通過數:')
    PevalOneMax(best_ind)

    print('出題方給的定價規律的預測通過數',TevalOneMax())
    t2 = time.clock()
    print(t2 - t1)

if __name__ == "__main__":
    # t1 = time.clock()
    main()
    # t2 = time.clock()
    # print(t2-t1)

下載資料檔案