Python实现单纯形法

import tkinter
import tkinter.filedialog
import tkinter.messagebox
import tkinter.ttk
import re
import numpy
import copy

##窗口设计
root=tkinter.Tk()

#窗口大小
root.title('单纯形法')
root['height']=250
root['width']=420

#放'目标函数:'
labelName=tkinter.Label(root,
                        text='目标函数:',
                        justify=tkinter.RIGHT,
                        anchor='e',
                        width=80)
labelName.place(x=30,y=30,width=80,height=20)

#放目标函数后的复选框
extreme_list=['max','min']

combo_extreme=tkinter.ttk.Combobox(root,
                                 width=50,
                                 values=extreme_list)

combo_extreme.current(1)
combo_extreme.place(x=110,y=30,width=50,height=20)
#放'='
labelName=tkinter.Label(root,
                        text='=',
                        justify=tkinter.RIGHT,
                        anchor='e',
                        width=80)
labelName.place(x=165,y=30,width=10,height=20)

#放目标函数框
text_objective_function=tkinter.Text(root,
                                            width=80,
                                            height=50)
start_text='30x1+50x2+10x3'
text_objective_function.insert(0.0,start_text)
text_objective_function.place(x=180,y=30,width=200,height=20)

text_objective_function.tag_add('link1','1.0','end')
def click1(event):
    text_objective_function.delete('1.0','end')
text_objective_function.tag_bind('link1','',click1)
#放'约束条件:'
labelName=tkinter.Label(root,
                        text='约束条件:',
                        justify=tkinter.RIGHT,
                        anchor='e',
                        width=80)
labelName.place(x=30,y=60,width=80,height=20)

#放约束条件框
text_constraint_condition=tkinter.Text(root,
                                            width=80,
                                            height=50)
start_text='2x1+3x2+4x3<=40;\nx1+2x2+2x3<=26;'
text_constraint_condition.insert(0.0,start_text)
text_constraint_condition.place(x=140,y=60,width=200,height=100)

text_constraint_condition.tag_add('link2','1.0','end')
def click(event):
    text_constraint_condition.delete('1.0','end')
text_constraint_condition.tag_bind('link2','',click)
  

#放'计算'钮
def Simplex():
    def get_x():
        ob=text_objective_function.get(0.0,'end')
        print
        x=[]
        for i in range(len(ob)):
            if ob[i]=='x':
                j=i+1
                temp_x=''
                while True:
                    try:
                        assert(type(int(ob[j]))==int)
                        temp_x=temp_x+ob[j]
                    except:
                        break
                    j=j+1
                x.append(int(temp_x))
        return x
    def get_co_of_ob():
        ob=text_objective_function.get(0.0,'end')
        #获得系数和运算符号
        ob_c=[]#放系数
        ob_s=[]#放运算符号
        for i in range(len(ob)):
            if ob[i]=='+':
                ob_s.append(ob[i])
            elif ob[i]=='-':
                ob_s.append(ob[i])
            elif ob[i]=='x':
                j=i#向前检索确定系数
                temp_c=''
                while True:
                    if j<=0:
                        break
                    if ob[j-1]=='.':
                        temp_c=ob[j-1]+temp_c
                        j=j-1
                    try:
                        assert(type(int(ob[j-1]))==int)
                        temp_c=ob[j-1]+temp_c
                    except:
                        break
                    j=j-1
                if temp_c=='':
                    ob_c.append(1)
                else:
                    ob_c.append(float(temp_c))
        #组合系数和运算符号为目标函数的系数
        co=[]
        if len(ob_c)!=len(ob_s):#第一项为正时
            co.append(ob_c[0])
            for i in range(len(ob_s)):
                if ob_s[i]=='+':
                    co.append(ob_c[i+1])
                else:
                    co.append(-ob_c[i+1])
        else:
            for i in range(len(ob_c)):
                if ob_s[i]=='+':
                    co.append(ob_c[i])
                else:
                    co.append(-ob_c[i])
        return co

    def get_co_of_tc():
        tc=text_constraint_condition.get(0.0,'end')
        all_tc=tc.replace('\n','').split(';')
        all_tc.pop()#每一个约束条件
        co=[]   #系数
        x_ma=[]
        for h in range(len(all_tc)):
            co.append([])
            temp_tc=all_tc[h]
            tc_c=[]
            tc_s=[]
            x_ma.append([])
            for i in range(len(temp_tc)):
                if temp_tc[i]=='+':
                    tc_s.append(temp_tc[i])
                elif temp_tc[i]=='-':
                    tc_s.append(temp_tc[i])
                elif temp_tc[i]=='x':
                    j=i#向前检索确定系数
                    k=i#向后检索确定x
                    temp_c=''
                    temp_x=''
                    while True:
                        try:
                            assert(type(int(temp_tc[k+1]))==int)
                            temp_x=temp_x+temp_tc[k+1]
                        except:
                            break
                        k=k+1
                    x_ma[h].append(int(temp_x))
                    while True:
                        if j<=0:
                            tc_s.append('+')
                            break
                        if temp_tc[j-1]=='.':
                            temp_c=temp_tc[j-1]+temp_c
                            j=j-1
                        try:
                            assert(type(int(temp_tc[j-1]))==int)
                            temp_c=temp_tc[j-1]+temp_c
                        except:
                            break
                        j=j-1
                    if temp_c=='':
                        tc_c.append(1)
                    else:
                        tc_c.append(float(temp_c))
                    
                elif temp_tc[i]=='<':
                    tc_c.append(1)
                    tc_s.append('+')
                elif temp_tc[i]=='>':
                    tc_c.append(1)
                    tc_s.append('-')
            #组合系数和运算符号为目标函数的系数
            for i in range(len(tc_c)):
                if tc_s[i]=='+':
                    co[h].append(tc_c[i])
                else:
                    co[h].append(-tc_c[i])
        #组合x_ma和co为系数矩阵
        #获得x_ma中最大值
        max_x_ma=x_ma[0][0]
        for i in range(len(x_ma)):
            for j in range(len(x_ma[i])):
                if x_ma[i][j]>max_x_ma:
                    max_x_ma=x_ma[i][j]
        #根据约束条件补满x_ma
        for i in range(len(x_ma)):
            while len(x_ma[i])!=len(co[i]):
                x_ma[i].append(max_x_ma+1)
                x.append(max_x_ma+1)
                max_x_ma=max_x_ma+1
        co_ma=[]
        for i in range(len(x_ma)):
            co_ma.append([])
            temp_index=0
            for j in range(len(x)):
                if x_ma[i][temp_index]==x[j]:
                    co_ma[i].append(co[i][temp_index])
                    temp_index=temp_index+1
                    if temp_index>=len(x_ma[i]):
                        break
                else:
                    co_ma[i].append(0)
            while len(co_ma[i])!=len(x):
                co_ma[i].append(0)
        return co_ma
    def get_re():
        tc=text_constraint_condition.get(0.0,'end')
        all_tc=tc.replace('\n','').split(';')
        all_tc.pop()
        re=[]
        for h in range(len(all_tc)):
            temp_re=''
            j=-1
            while True:
                if all_tc[h][j]=='-':
                    temp_re='-'+temp_re
                    break
                try:
                    assert(type(int(all_tc[h][j]))==int)
                    temp_re=all_tc[h][j]+temp_re
                except:
                    break
                j=j-1
            re.append(int(temp_re))
        return re
    #目标函数中的变量
    x=get_x()
    #print('x=',x)
    n=len(x)
    #print('n=',n)
    #目标函数中变量的系数
    co_ob=get_co_of_ob()
    #加入松弛变量和剩余变量后的约束条件的系数矩阵
    co_ma=get_co_of_tc()
    #print('co_ma=',co_ma)
    #约束条件中的资源系数
    re=get_re()
    #print('re=',re)
    #化为标准型
    def standard():
        extreme=combo_extreme.get()
        #更新资源系数
        for i in range(len(re)):
            if re[i]<0:
                re[i]=-re[i]
                for j in range(len(co_ma[i])):
                    co_ma[i][j]=-co_ma[i][j]
        #更新目标函数系数
        if extreme=='max':
            pass
        else:
            for i in range(len(co_ob)):
                co_ob[i]=-co_ob[i]
        while(len(co_ob)!=len(co_ma[0])):
            co_ob.append(0)
        #print('co_ob=',co_ob)
        n=len(co_ma)
        E=numpy.identity(n)
        E_=[]
        for i in range(n):
            E_.append([])
            for j in range(n):
                E_[i].append(-E[i][j])
        #判断系数矩阵后n维是否为单位阵
        temp_ma=[]
        for i in range(n):
            temp_ma.append([])
            for j in range(len(co_ma[i])-n,len(co_ma[i])):
                temp_ma[i].append(co_ma[i][j])
        #print('temp_ma=',temp_ma)
        #是否直接为
        log=temp_ma==E
        try:
            assert(log.all()==True)
            #print('当前已为标准型')
        except:
            #是否加个负号为
            log_=temp_ma==E_
            try:
                assert(log_.all()==True)
                #print('当前加负号后为标准型')
                for i in range(len(co_ma)):
                    for j in range(len(co_ma[0])):
                        co_ma[i][j]=-co_ma[i][j]
                for i in range(len(re)):
                    re[i]=-re[i]
            except:
                #是否仅某一行为负
                op=0#op为1时完成标准型的转化
                for h in range(len(E)):
                    temp_E=copy.deepcopy(E)
                    temp_E[h][h]=-1
                    temp_log=temp_E==temp_ma
                    try:
                        assert(temp_log.all()==True)
                        #print('当前第{0}行为-1'.format(h+1))
                        co_ob.append(0)
                        co_ob[len(co_ma[h])-len(E)+h+1]=-9999
                        for i in range(len(E)):
                            #各行增加一列
                            co_ma[i].append(0)
                            #-1行为-1
                            if i==h:
                                co_ma[i][len(co_ma[h])-len(E)-1]=-1
                            #剩余行为0
                            else:
                                co_ma[i][len(co_ma[h])-len(E)]=0
                        #后接个单位阵
                        for i in range(len(E)):
                            for j in range(len(E)):
                                if i==j:
                                    co_ma[i][len(co_ma[i])-len(E)+j]=1
                                else:
                                    co_ma[i][len(co_ma[i])-len(E)+j]=0
                        op=1
                        break
                    except:
                        pass
                if op==0:
                    for i in range(n):
                        for j in range(n):
                            co_ma[i].append(int(E[i][j]))
                        co_ob.append(-9999)
                 
        time1=len(co_ma[0])-len(co_ob)
        for i in range(time1):
            co_ob.append(0)
        max_x=x[0]
        for i in range(len(x)):
            if x[i]>max_x:
                max_x=x[i]
        time2=len(co_ob)-len(x)
        for i in range(time2):
            max_x=max_x+1
            x.append(max_x)
        return co_ma,re,co_ob,x

    A,b,C,X=standard()
    print('A=',A)
    print('b=',b)
    print('C=',C)
    print('x=',x)
    C_display=[]
    for i in range(len(C)):
        if C[i]==9999:
            C_display.append('M')
        elif C[i]==-9999:
            C_display.append('-M')
        else:
            C_display.append(str(C[i]))
    #print('C_display=',C_display)
    temp_A=copy.deepcopy(A)
    temp_b=copy.deepcopy(b)
    #获得检验数
    def get_sigma():
        C_B=[]
        for j in range(len(x_B)):
            for i in range(len(x)):
                if x[i]==x_B[j]:
                    C_B.append(C[i])
        #print('C_B=',C_B)
        
        C_B_display=[]
        for j in range(len(x_B)):
            for i in range(len(x)):
                if x[i]==x_B[j]:
                    C_B_display.append(C_display[i])
        #print('C_B_display=',C_B_display)
        
        sigma=[]
        for i in range(len(temp_A[0])):
            temp_sigma=C[i]
            for j in range(len(C_B)):
                temp_sigma=temp_sigma-temp_A[j][i]*C_B[j]
            sigma.append(temp_sigma)
            
        #显示M
        sigma_display=[]
        for i in range(len(C)):
            num_sigma=0
            str_sigma='0'
            #print('C_display[{0}]='.format(i),C_display[i])
            try:
                num_sigma=float(C_display[i])
            except:
                if C_display[i][:-1]=='-':
                    str_sigma=-1
                else:
                    str_sigma=C_display[i][:-1]
            #print('num_sigma=',num_sigma)
            #print('str_sigma=',str_sigma)
            for j in range(len(C_B_display)):
                #print('C_B_display[{0}]='.format(j),C_B_display[j])
                try:
                    num_sigma=num_sigma-temp_A[j][i]*float(C_B_display[j])
                except:
                    temp_s=''#存j此次的系数
                    h=0
                    while(C_B_display[j][h]=='-' or type(C_B_display[j][h])==float):
                        temp_s=temp_s+C_B_display[j][h]
                        h=h+1
                        if h>=len(C_B_display[j]):
                            break
                    #print('temp_s=',temp_s)
                    if temp_s=='':
                        str_sigma=str(float(str_sigma)-1*temp_A[j][i])
                    elif temp_s=='-':
                        str_sigma=str(float(str_sigma)+1*temp_A[j][i])
                    else:
                        str_sigma=str(float(str_sigma)+int(temp_s)+temp_A[j][i])
                #print('num_sigma=',num_sigma)
                #print('str_sigma=',str_sigma)
                if num_sigma==0 and float(str_sigma)!=0:
                    temp_sigma_display=str(round(float(str_sigma),2))+'M'
                elif num_sigma!=0 and float(str_sigma)==0:
                    temp_sigma_display=str(round(num_sigma,2))
                elif num_sigma==0 and float(str_sigma)==0:
                    temp_sigma_display=0
                else:
                    if float(str_sigma)<0:
                        temp_sigma_display=str(round(num_sigma,2))+'-'+str(-round(float(str_sigma),2))+'M'
                    else:
                        temp_sigma_display=str(round(num_sigma,2))+'+'+str(round(float(str_sigma),2))+'M'
            #print('temp_sigma_display=',temp_sigma_display)
            sigma_display.append(temp_sigma_display)
        return sigma,sigma_display
    #获得theta
    def get_theta():
        theta=[]
        theta_display=[]
        print()
        for i in range(len(b)):
            temp_theta=temp_b[i]/temp_A[i][col]
            if temp_theta<0:
                theta.append(9999)
                theta_display.append('-')
            else:
                theta.append(round(temp_theta,2))
                theta_display.append(str(round(temp_theta,2)))
        return theta,theta_display
    #更新temp_A temp_b x_B
    def update():
        for i in range(len(temp_A)):
            if i!=ln:
                k=temp_A[i][col]/temp_A[ln][col]
                #先变非选中行
                temp_b[i]=temp_b[i]-k*temp_b[ln]
                for j in range(len(temp_A[i])):
                    temp_A[i][j]=temp_A[i][j]-k*temp_A[ln][j]
        #再变选中行
        k=temp_A[ln][col]
        for j in range(len(temp_A[ln])):
            temp_A[ln][j]=temp_A[ln][j]/k
        temp_b[ln]=temp_b[ln]/k
        #print('temp_A=',temp_A)
        #print('temp_b=',temp_b)
        #最后变x_B
        x_B[ln]=x[col]
        return temp_A,temp_b,x_B
    x_B=[]
    for i in range(len(b)):
        x_B.append(x[len(x)-len(b)+i])
    #print('x_B=',x_B)
    t=0
    all_col=[]
    all_ln=[]
    all_A=[A]
    all_b=[b]
    all_x_B=[copy.deepcopy(x_B)]
    all_sigma=[]
    all_theta=[]
    while True:
        try:
            for i in range(len(temp_b)):
                assert(temp_b[i]>0)
            pass
        except:
            #print('改问题为无可行解')
            case=0
            break
        #print('\n')
        sigma,sigma_display=get_sigma()
        #print('sigma=',sigma)
        #print('sigma_display=',sigma_display)
        all_sigma.append(copy.deepcopy(sigma_display))
        try:
            for i in range(len(sigma)):
                assert(sigma[i]<=0)
            #print('end')
            case=1
            break
        except:
            pass
        t=t+1
        if t>20:
            case=-1
            break
        col=sigma.index(max(sigma))
        all_col.append(copy.deepcopy(col))
        #print('col=',col)
        theta,theta_display=get_theta()
        #print('theta=',theta)
        ln=theta.index(min(theta))
        all_ln.append(copy.deepcopy(ln))
        #print('ln=',ln)
        all_theta.append(copy.deepcopy(theta_display))
        temp_A,temp_b,x_B=update()
        all_A.append(copy.deepcopy(temp_A))
        all_b.append(copy.deepcopy(temp_b))
        all_x_B.append(copy.deepcopy(x_B))
        #print('x_B=',x_B)
    #print('all_ln=',all_ln)
    #print('all_col=',all_col)
    #print('all_A=',all_A)
    #print('all_b=',all_b)
    #print('all_x_B=',all_x_B)
    #print('all_sigma=',all_sigma)
    #print('all_theta=',all_theta)
    if case==-1:#无穷解
        tkinter.messagebox.showerror('error',
                                     message='该问题为无界解')
    if case==0:#无解
        tkinter.messagebox.showerror('error',
                                     message='该问题无最优解')
    if case==1:#有唯一解
        top=tkinter.Toplevel()
        top['height']=230
        top['width']=250
        top.title('最优解')
        labelvalue=tkinter.Label(top,
                                 text='该问题有最优解:')
        labelvalue.place(x=10,y=20,width=150)
        for i in range(n):
            for j in range(len(temp_b)):
                if x[i]==x_B[j]:
                    temp_x=x_B[j]
                    temp_x='x{0}='.format(x[i])+str(round(temp_b[j],2))
                    break
                temp_x='x{0}=0'.format(x[i])
            labelx=tkinter.Label(top,
                                 text=temp_x)
            labelx.place(x=50,y=30+20*(i+1),width=80)
        value=0
        for i in range(len(temp_b)):
            value=value+C[x_B[i]-1]*temp_b[i]
        value='目标函数值为:'+str(round(value,2))
        labelvalue=tkinter.Label(top,
                                 text=value)
        labelvalue.place(x=10,y=30+20*(n+2),width=150)
        ###绘制单纯形表表格
        def open():
            top2=tkinter.Toplevel()
            top2.title('单纯形表')
            size='{0}x{1}'.format(83*(4+len(all_A[0][0])),30*(3+len(all_A[0])))
            top2.geometry(size)
            def step(n):
                columns=['0-1','0-2','0-3']
                for i in x:
                    columns.append('{0}'.format(i))
                columns.append('2-1')
                tree=tkinter.ttk.Treeview(top2,height=1+len(all_A[n])+1,columns=columns,show='headings')

                for i in range(len(columns)):
                    tree.column(columns[i],width=80,anchor='center')
                    
                tree.heading('0-1',text='')
                tree.heading('0-2',text='cj->')
                tree.heading('0-3',text='')
                w=0
                for i in range(len(columns)-4):
                        tree.heading(columns[i+3],text=C_display[w])
                        w=w+1
                tree.heading('2-1',text='theta')
                values_0=['C_B','x_B','b']
                for i in range(len(x)):
                    values_0.append('x'+str(x[i]))
                tree.insert("",0,values=values_0)
                for i in range(len(all_x_B[n])):
                    values=[str(C_display[x.index(all_x_B[n][i])])]
                    values.append('x'+str(all_x_B[n][i]))
                    values.append(str(round(all_b[n][i],2)))
                    for j in range(len(all_A[n][i])):
                        try:
                            assert(i==all_ln[n] and j==all_col[n])
                            values.append('['+str(round(all_A[n][i][j],2))+']')
                        except:
                            values.append(str(round(all_A[n][i][j],2)))
                    try:
                        values.append(all_theta[n][i])
                    except:
                        pass
                    tree.insert("",i+1,values=values)
                values=['','sigma','']
                for i in range(len(all_sigma[n])):
                    values.append(all_sigma[n][i])
                tree.insert("",1+len(all_x_B[n]),values=values)
                tree.place(x=1,y=1)
                
            step(0)
            
            q=[]
            for i in range(len(all_A)):
                q.append(i)
            def step_up():
                q.pop(0)
                #print('q=',q)
                step(q[0])
                if len(q)==1:
                    label=tkinter.Label(top2,
                                        text='当前为最后一张单纯形表',
                                        width=200)
                    label.place(x=83*(4+len(all_A[0][0]))-350,y=30*(3+len(all_A[0]))-40,width=200,height=20)
                    button_drop=tkinter.Button(top2,
                                               text='退出',
                                               command=top2.destroy)
                    button_drop.place(x=83*(4+len(all_A[0][0]))-130,y=30*(3+len(all_A[0]))-40,width=60,height=30)
            button_next=tkinter.Button(top2,
                                           text='下一张',
                                           command=step_up)
            button_next.place(x=83*(4+len(all_A[0][0]))-130,y=30*(3+len(all_A[0]))-40,width=60,height=30)
                
                
            
            top2.mainloop()
        button_open=tkinter.Button(top,
                                   text='查看单纯形表',
                                   command=open)
        button_open.place(x=100,y=80+20*(n+2),width=100,height=30)
        button_out=tkinter.Button(top,
                                  text='退出',
                                  command=top.destroy)
        button_out.place(x=10,y=80+20*(n+2),width=60,height=30)
button_drop_out=tkinter.Button(root,
                            text='计算',
                            command=Simplex)
button_drop_out.place(x=260,y=180,width=60,height=30)


#放'退出'钮
button_drop_out=tkinter.Button(root,
                            text='退出',
                            command=root.destroy)
button_drop_out.place(x=150,y=180,width=60,height=30)

root.mainloop()

你可能感兴趣的:(tkinter)