17、分支定界法

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 18 16:25:16 2019
@author: zhangchaoyu
"""
import copy
import math
 
def show_1(C, D, A, B, X, vc, vd):
    
    result = []
    result.append(copy.deepcopy(C+vc))
    result.append(copy.deepcopy(D+vd))
    for i in range(len(A)):
        result.append(copy.deepcopy(A[i]+[B[i]]))
    for r in result:
        print(r)
    print("当前解:")
    print("X="+str(X))
    print()
 
def find_new_1(D, A, B):
    idex_negative = -1
    for i in range(len(D)):
        if D[i] < 0 and (idex_negative == -1 or (idex_negative != -1 and D[i] < D[idex_negative])):
            idex_negative = i
            
    if idex_negative == -1:
        print("第一阶段检验数无小于0项,已至最优")
        return -1
    
    flag = -1
    row = -1
    rate = -1
    for i in range(len(B)):
        if A[i][idex_negative] <= 0:
            continue
        if rate == -1 or (rate != -1 and rate > B[i]/A[i][idex_negative]):
            flag = 1
            row = i
            rate = B[i]/A[i][idex_negative]
    if flag == 1:
        return [row, idex_negative]
    else:
        print("第一阶段检验数无小于0项,已至最优")
        return -1
 
def adjust_1(idex_row, idex_col, A, B, C, D, idexs, X, vc, vd):
    
    m = len(B)
    n = len(D)
    
    idexs[idex_row] = idex_col
    
    rate = A[idex_row][idex_col]
    for i in range(n):
        A[idex_row][i] /= rate
    B[idex_row] /= rate
    
    for i in range(m):
        if i == idex_row:
            continue
        rate = A[i][idex_col]/A[idex_row][idex_col]
        B[i] -= rate*B[idex_row]
        for j in range(n):
            A[i][j] -= rate*A[idex_row][j]
    
    rate = C[idex_col]/A[idex_row][idex_col]
    for i in range(n):
        C[i] -= rate*A[idex_row][i]
    vc[0] -= rate*B[idex_row]
    
    rate = D[idex_col]/A[idex_row][idex_col]
    for i in range(n):
        D[i] -= rate*A[idex_row][i]
    vd[0] -= rate*B[idex_row]
    
    for i in range(len(X)):
        if i not in idexs:
            X[i] = 0
        else:
            for j in range(len(idexs)):
                if i == idexs[j]:
                    X[i] = B[j]
 
def find_new_2(C, A, B):
    idex_positive = -1
    for i in range(len(C)):
        if C[i] > 0 and (idex_positive == -1 or (idex_positive != -1 and C[i] > C[idex_positive])):
            idex_positive = i
    
    if idex_positive == -1:
        print("第二阶段检验数无大于0项,已至最优")
        return -1
    
    flag = -1
    row = -1
    rate = -1
    flag_n = -1
    for i in range(len(B)):
        if A[i][idex_positive] < 0:
            flag_n = 1
        if A[i][idex_positive] <= 0:
            continue
        if rate == -1 or (rate != -1 and rate > B[i]/A[i][idex_positive]):
            flag = 1
            row = i
            rate = B[i]/A[i][idex_positive]
    if flag == 1:
        return [row, idex_positive]
    else:
        if flag_n == 1:
            print("第二阶段解无界")
            return -3
        else:
            print("第二阶段检验数无大于0项,已至最优")
            return -1
 
def adjust_2(idex_row, idex_col, A, B, C, idexs, X, v):
    
    m = len(B)
    n = len(C)
    
    idexs[idex_row] = idex_col
    
    rate = A[idex_row][idex_col]
    for i in range(n):
        A[idex_row][i] /= rate
    B[idex_row] /= rate
    
    for i in range(m):
        if i == idex_row:
            continue
        rate = A[i][idex_col]/A[idex_row][idex_col]
        B[i] -= rate*B[idex_row]
        for j in range(n):
            A[i][j] -= rate*A[idex_row][j]
    
    rate = C[idex_col]/A[idex_row][idex_col]
    for i in range(n):
        C[i] -= rate*A[idex_row][i]
    v[0] -= rate*B[idex_row]
    
    for i in range(len(X)):
        if i not in idexs:
            X[i] = 0
        else:
            for j in range(len(idexs)):
                if i == idexs[j]:
                    X[i] = B[j]
 
def show_2(C, A, B, X, v):
    
    result = []
    result.append(copy.deepcopy(C+v))
    for i in range(len(A)):
        result.append(copy.deepcopy(A[i]+[B[i]]))
    for r in result:
        print(r)
    print("当前解:")
    print("X="+str(X))
    print()
 
def sub_data_integer(x):
    
    if math.ceil(100*x)/100 - x <= 1e-10:
        return math.ceil(100*x)/100
    
    if x - math.floor(100*x)/100 <= 1e-10:
        return math.floor(100*x)/100
    
    return x
 
def data_integer(A, B, C, D, X, vc, vd):
    
    for i in range(len(A)):
        for j in range(len(A[i])):
            A[i][j] = sub_data_integer(A[i][j])
    
    for i in range(len(B)):
        B[i] = sub_data_integer(B[i])
        
    for i in range(len(C)):
        C[i] = sub_data_integer(C[i])
    
    for i in range(len(D)):
        D[i] = sub_data_integer(D[i])
    
    for i in range(len(X)):
        X[i] = sub_data_integer(X[i])
        
    vc[0] = sub_data_integer(vc[0])
    vd[0] = sub_data_integer(vd[0])
 
def simplex(C0, A0, B0):
    """
    返回值为[flag,X],flag=-2表示正常,flag=-3表示无界,flag=-4表示无解
    """    
    
    C = copy.deepcopy(C0)
    A = copy.deepcopy(A0)
    B = copy.deepcopy(B0)

    for i in range(len(B)):
        if B[i] >= 0:
            continue
        B[i] = -B[i]
        for j in range(len(A[i])):
            A[i][j] = -A[i][j]

    C = C + [0 for i in range(len(B0))]
    for i in range(len(A)):
        temp = [0 for j in range(len(A))]
        temp[i] = 1
        A[i] = A[i] + copy.deepcopy(temp)
    D = [sum([-A[j][i] for j in range(len(B))]) for i in range(len(C0))] + [0 for i in range(len(B0))]
    vc = [0]
    vd = [sum([-B[i] for i in range(len(B))])]
    idexs = [len(C0)+i for i in range(len(A))]
    X = [0 for i in range(len(C0))] + copy.deepcopy(B)
    
    #开始第一阶段迭代计算
    loop = 0
    print("第一阶段第"+str(loop)+"次迭代后:")
    show_1(C, D, A, B, X, vc, vd)
    idex = find_new_1(D, A, B)
    
    while True:
        if idex == -1:
            break
        idex_row = idex[0]
        idex_col = idex[1]
        adjust_1(idex_row, idex_col, A, B, C, D, idexs, X, vc, vd)
        data_integer(A, B, C, D, X, vc, vd)
        loop += 1
        print("第一阶段第"+str(loop)+"次迭代后:")
        show_1(C, D, A, B, X, vc, vd)
        idex = find_new_1(D, A, B)
    
    #统计第一阶段结果,判断是否有可行解
    #planC:综合考虑
    if vd[0] != 0:
        print("无可行解,当前近似解X="+str(X[:len(C0)]))
        return [-4,X[:len(C0)]]
    
    tests = [len(C0)+i for i in range(len(A))]
    idexs_del = []
    for i in range(len(idexs)):
        if idexs[i] in tests:
            if B[i] > 0:
                print("无可行解,当前近似解X="+str(X[:len(C0)]))
                return [-4,X[:len(C0)]]
            idex_row = 0
            for j in range(len(A)):
                if A[j][idexs[i]] != 0:
                    idex_row = j
            if sum([abs(A[idex_row][j]) for j in range(len(C0))]) == 0:
                idexs_del.append(i)
            else:
                idex_col = 0
                for i in range(len(C0)):
                    if A[idex_row][i] != 0:
                        idex_col = i
                        break
                adjust_1(idex_row, idex_col, A, B, C, D, idexs, X, vc, vd)
                data_integer(A, B, C, D, X, vc, vd)
                
    B1 = []
    A1 = []
    for i in range(len(A)):
        if i in idexs_del:
            continue
        B1.append(copy.deepcopy(B[i]))
        A1.append(copy.deepcopy(A[i]))
    B = B1
    A = A1
    
    #有可行解后,重新建立单纯形表
    C = C[:len(C0)]
    for i in range(len(A)):
        A[i] = A[i][:len(C0)]
    X = X[:len(C0)]
    v = vc
    
    #开始第二阶段迭代计算
    loop = 0
    print("第二阶段第"+str(loop)+"次迭代后:")
    show_2(C, A, B, X, v)
    idex = find_new_2(C, A, B)
    
    while True:
        if idex == -1 or idex == -3:
            break
        idex_row = idex[0]
        idex_col = idex[1]
        adjust_2(idex_row, idex_col, A, B, C, idexs, X, v)
        data_integer(A, B, C, D, X, vc, vd)
        loop += 1
        print("第二阶段第"+str(loop)+"次迭代后:")
        show_2(C, A, B, X, v)
        idex = find_new_2(C,A,B)
    
    print("当前解:")
    print("X="+str(X))
    print("最优值:")
    print(sum([C0[i]*X[i] for i in range(len(X))]))
    if idex == -3:
        return [idex, X]
    else:
        return [-2,X] 
 
def sub_BBM(C0, A0, B0, I0):
    
    C00 = copy.deepcopy(C0)
    A00 = copy.deepcopy(A0)
    B00 = copy.deepcopy(B0)
    
    X = simplex(C00, A00, B00)
    if X[0] <= -3:
        return X
    
    idex = -1
    for i in range(I0):
        if X[1][i] != int(X[1][i]):
            idex = i
            break
        
    if idex == -1:
        return X
    
    C01 = copy.deepcopy(C00+[0])
    A01 = []
    for j in range(len(A00)):
        A01.append(copy.deepcopy(A00[j]+[0]))
    temp = [0 for j in range(len(C01))]
    temp[idex] = 1
    temp[-1] = 1
    A01.append(copy.deepcopy(temp))
    B01 = copy.deepcopy(B00+[int(X[1][idex])])
    X1 = sub_BBM(C01, A01, B01, I0)
    
    C02 = copy.deepcopy(C00+[0])
    A02 = []
    for j in range(len(A00)):
        A02.append(copy.deepcopy(A00[j]+[0]))
    temp = [0 for j in range(len(C02))]
    temp[idex] = 1
    temp[-1] = -1
    A02.append(copy.deepcopy(temp))
    B02 = copy.deepcopy(B00+[int(X[1][idex])+1]) 
    X2 = sub_BBM(C02, A02, B02, I0)
    
    if X1[0] == -2:
        if X2[0] == -2 and sum([C01[i]*X1[1][i] for i in range(len(X1[1]))]) < sum([C02[i]*X2[1][i] for i in range(len(X2[1]))]):
            return [X2[0],X2[1][:-1]]
        if X2[0] == -3:
            return [X2[0],X2[1][:-1]]
    if X1[0] == -4 and X2[0] != -4:
        return [X2[0],X2[1][:-1]]
    return [X1[0],X1[1][:-1]]
 
def BBM(C0, A0, B0, I0):
    
    X = sub_BBM(C0, A0, B0, I0)
    
    if X[0] == -2:
        print("正常解X:"+str(X[1]))
        print(X[1])
        print("最优值:")
        print(sum([C0[i]*X[1][i] for i in range(len(X[1]))]))
    elif X[0] == -3:
        print("无界解,其中一个可行解X:")
        print(X[1])
    else:
        print("无可行解")
    
    return X[1]

def examples_test(examples, test):
    result = []
    
    for i in range(len(examples)):
        C0 = examples[i][0]
        A0 = examples[i][1]
        B0 = examples[i][2]
        I0 = examples[i][3]
        X = BBM(C0, A0, B0, I0)
        result.append(sum([C0[i]*X[i] for i in range(len(X))]))
        
    for i in range(len(result)):
        print(str(result[i]) + "   " +  str(test[i]))



examples = []
examples.append([[20,10,0,0],[[5,4,1,0],[2,5,0,1]],[24,13],2])
examples.append([[40,90,0,0],[[9,7,1,0],[7,20,0,1]],[56,70],2])
examples.append([[3,2,0,0],[[2,3,1,0],[4,1,0,1]],[14.5,16.5],2])
examples.append([[3,2,0,0],[[2,3,1,0],[2,1,0,1]],[14,9],2])
examples.append([[1,1,0,0],[[1,9/14,1,0],[-2,1,0,1]],[51/14,1/3],2])
examples.append([[1,1,0,0],[[2,1,1,0],[4,5,0,1]],[6,20],2])
examples.append([[3,-1,0,0,0],[[3,-2,1,0,0],[5,4,0,-1,0],[2,1,0,0,1]],[3,10,5],2])

test = [90, 340, 13, 14, 4, 4, 1]

#检验所有例子和结果
examples_test(examples, test)

C0 = examples[-1][0]
A0 = examples[-1][1]
B0 = examples[-1][2]
I0 = examples[-1][3]
X = BBM(C0, A0, B0, I0)

 

你可能感兴趣的:(运筹优化,机器学习基础算法实现)