線性規(guī)劃之單純形解法Java實(shí)現(xiàn)

單純形法

理解完這個(gè)算法后大家也可以打一下,打碼過程中,會(huì)有很多很多的錯(cuò)誤要排查,編碼一小時(shí)从诲,排錯(cuò)三小時(shí),不過從中可以練習(xí)到蠻多的(運(yùn)行截圖在文末)
  • 輸入線性規(guī)劃標(biāo)準(zhǔn)型的數(shù)據(jù)(n個(gè)變量靡羡,m個(gè)約束條件)

    • C //價(jià)值系數(shù)向量
    • X //決策變量向量
    • A //工藝系數(shù)矩陣
    • b //資源常數(shù)
    • yita //檢驗(yàn)數(shù)
    • theta //b除以換入變量在每行的系數(shù)系洛,即單純形表最右端參數(shù)
  • 找基可行解

    • 簡(jiǎn)單的拿最后m個(gè)決策變量,后期可優(yōu)化
  • 判斷是否最優(yōu)解:計(jì)算并判斷是否每一個(gè)檢驗(yàn)數(shù)yita都小于等于0

      • 輸出最優(yōu)解:max z = CX
      • 確定換入變量
        • 檢驗(yàn)數(shù)大于0中略步,檢驗(yàn)數(shù)最大的非基變量
      • 確定換出變量
        • 計(jì)算theta
        • 判斷是否線性規(guī)劃結(jié)果為無(wú)界解:theta的系數(shù)是否均小于或等于0
            • 終止運(yùn)算描扯,輸出結(jié)果為無(wú)界解
            • 取theta[i]中大于0且最小的行所對(duì)應(yīng)的基變量作為換出變量
      • 旋轉(zhuǎn)運(yùn)算
        • 換入變量的所對(duì)應(yīng)的方程中左右兩邊同除換入變量的系數(shù)
        • 再次循環(huán),重新判斷是否最優(yōu)解

所有函數(shù)

  • void inputNums() //輸入數(shù)據(jù)
  • void findBasedVariables() //找基變量
  • bool isOptimum() //是否最優(yōu)解
  • int getVariableIn() //確定換入變量
  • int getVariableOut() //確定換出變量
  • void updateVectors() //更新旋轉(zhuǎn)運(yùn)算后的矩陣
  • private static void printVector() //輸出系數(shù)矩陣
  • void printOptimun() //輸出最優(yōu)解

先在main函數(shù)中寫好主要邏輯纳像,再具體實(shí)現(xiàn)

public static void main(String[] args) {
        //輸入數(shù)據(jù)荆烈,為了簡(jiǎn)單起見,我們的數(shù)據(jù)直接在代碼中敲入竟趾,這個(gè)函數(shù)等測(cè)試完后加
        inputNums(); 
        //找初始基變量
        findBasedVariables();
        //判斷是否最優(yōu)解
        while (!isOptimum()) {
            //找換入變量
            idxOfIn = getVariableIn();
            printVector();
            //找換出變量
            idxOfOut = getVariableOut();
            //如果idxOfOut返回-1,則該線性規(guī)劃問題有無(wú)界解
            if(idxOfOut == -1)
                return;
            //旋轉(zhuǎn)運(yùn)算宫峦,更新矩陣
            updateVectors();
            printVector();
            System.out.println("\n");
        }
        //輸出最優(yōu)解
        printOptimum();
    }

全局變量

private static double A[][] = { { 1, 2, 1, 0, 0 }, 
                                    { 2, 1, 0, 1, 0 },
                                    { 4, 3, 0, 0, 1 } };// 系數(shù)矩陣
    
    private static int m = A.length; //m個(gè)方程
    private static int n = A[0].length; //n個(gè)決策變量
    
    private static double C[] = { 3, 2, 0, 0, 0 }; // 價(jià)值系數(shù)
    
    private static double b[] = { 5, 4 ,9}; // 資源常數(shù)
    
    private static double theta[] = new double[m]; //b的檢驗(yàn)數(shù)
    
    private static int basedVar[] = new int[m]; // 基變量岔帽,存基變量的下標(biāo),從1開始標(biāo)號(hào)(區(qū)別于數(shù)組存儲(chǔ)習(xí)慣)
    
    private static double yita[] = new double[n]; //檢驗(yàn)數(shù)导绷,有n個(gè)決策變量的檢驗(yàn)數(shù)
    
    private static double result = -1; //結(jié)果
    
    private static int idxOfIn = -1; //換入變量的下標(biāo)
    
    private static int idxOfOut = -1; //換出變量的下標(biāo)

inputNums()

// 輸入數(shù)據(jù)犀勒,先在代碼中寫入數(shù)據(jù),后期再加,先把初始檢驗(yàn)數(shù)賦值為價(jià)值系數(shù)
    private static void inputNums() {
        for (int i = 0; i < yita.length; i++) {
            yita[i] = C[i]; //yita為檢驗(yàn)數(shù)
        }
    }

findBasedVariables()

// 找基變量贾费,簡(jiǎn)單的拿最后m個(gè)決策變量钦购,后期可優(yōu)化,存儲(chǔ)在basedVar數(shù)組中
    private static void findBasedVariables() {
        
        //取n個(gè)決策變量的最后m個(gè)作基變量
        for (int i = 0; i < m; i++) {
            //basedVar[i] = n-i; 
            //改變存放順序?yàn)檎龜?            basedVar[m-i-1] = n-i ;
        }
        System.out.println("基變量為:");
        for (int i = 0; i < basedVar.length; i++) {
            System.out.print("x" + (basedVar[i]) + "\t");
        }
        System.out.println();
    }

isOptimum()

// 判斷是否最優(yōu)解褂萧,并計(jì)算檢驗(yàn)數(shù)yita向量
    private static boolean isOptimum() {
        //換入變量代替換出變量
        if(idxOfIn != -1 && idxOfOut != -1){
            //第idxOfOut個(gè)基變量換為x idxOfIn  
            basedVar[idxOfOut] = idxOfIn+1;
        }
        //更新檢驗(yàn)數(shù)
        for (int i = 0; i < n; i++) {
            double temp = yita[i];
            for (int j = 0; j < m; j++) {
                temp -= A[j][i] * C[basedVar[j] -1]; 
            }
            yita[i] = temp;
        }
        
        boolean hasPossitiveYita = false;
        for (int i = 0; i < yita.length; i++) {
            if(yita[i] > 0)
                hasPossitiveYita = true;
        }
        System.out.println("是否最優(yōu)解:" + !hasPossitiveYita);
        return !hasPossitiveYita;
    }

getVariableIn()

// 確定換入變量押桃,返回?fù)Q入變量的下標(biāo)-1
    private static int getVariableIn() {
        //遍歷檢驗(yàn)數(shù)
        int index = 0;
        System.out.println("檢驗(yàn)數(shù)如下:");
        for (int i = 0; i < yita.length; i++) {
             System.out.print(yita[i] + "\t");
             if(yita[i] > yita[index]){
                 index = i;
             }
        }
        System.out.println();
        System.out.println("換入變量是x" + (index+1));
        return index;
    }

getVariableOut()

// 確定換出變量,返回?fù)Q出變量在基變量向量中的下標(biāo)
    private static int getVariableOut() {
        
        System.out.println("theta:");
        for (int i = 0; i < m; i++) {
            if( Double.compare(A[i][idxOfIn], 0) != 0)
                theta[i] = b[i] / A[i][idxOfIn];
            else {
                theta[i] = 0;
            }
            System.out.print(theta[i] + "\t");
        }
        System.out.println();

        int index = 0;
        for (int i = 0; i < theta.length; i++) {
            if(theta[i] <= 0){
                System.out.println("該方程有無(wú)界解...");
                return -1;
            }else {
                if(theta[i] < theta[index])
                    index = i;
            }
        }
        System.out.println("換出變量是:x" + (basedVar[index]));
        return index;
    }

updateVectors()

// 更新旋轉(zhuǎn)運(yùn)算后的矩陣
    private static void updateVectors() {
        //m個(gè)方程导犹,n個(gè)變量
        //將主元系數(shù)化為1
        //防止迭代中主元的值被改變后引起 其它系數(shù)除主元的新值唱凯,將主元的原值存于temp
        double temp = A[idxOfOut][idxOfIn]; 
        for (int i = 0; i < n; i++) {
            A[idxOfOut][i] /= temp;
        }
        b[idxOfOut] /= temp;
        
        System.out.println("\n將主元系數(shù)化為1");
        printVector();
        //主元所在列其余元素系數(shù)要化為0,即:主元列中谎痢,非主元所在行均減去 主元系數(shù)分之一*A[m][n]
        for (int i = 0; i < m; i++) {
            //若是換出變量所對(duì)應(yīng)行磕昼,則該行不用換算
            double temp1 = A[i][idxOfIn]/A[idxOfOut][idxOfIn]; 
            if(i != idxOfOut){
                for (int j = 0; j < n; j++) {
                    A[i][j] -= A[idxOfOut][j]*temp1;
                }
                b[i] -= b[idxOfOut] * temp1;
            }
        }
        System.out.println("完成一次矩陣旋轉(zhuǎn)運(yùn)算...");
    }

printVector()

//輸出系數(shù)矩陣
    private static void printVector() {
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(A[i][j] + "\t");
            }
            System.out.println(b[i]);
        }
        System.out.println("-----------------------------------------------");
    }

printOptimum()

//輸出最優(yōu)解
    private static void printOptimum() {
        result = 0;
        for (int i = 0; i < basedVar.length; i++) {
            result += C[basedVar[i]-1] * b[i];
        }
        System.out.println("最優(yōu)解:z = " + result);
    }
image.png

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市节猿,隨后出現(xiàn)的幾起案子票从,更是在濱河造成了極大的恐慌,老刑警劉巖滨嘱,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峰鄙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡九孩,警方通過查閱死者的電腦和手機(jī)先馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躺彬,“玉大人煤墙,你說我怎么就攤上這事∠苡担” “怎么了仿野?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)她君。 經(jīng)常有香客問我脚作,道長(zhǎng),這世上最難降的妖魔是什么缔刹? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任球涛,我火速辦了婚禮,結(jié)果婚禮上校镐,老公的妹妹穿的比我還像新娘亿扁。我一直安慰自己,他們只是感情好鸟廓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布从祝。 她就那樣靜靜地躺著襟己,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牍陌。 梳的紋絲不亂的頭發(fā)上擎浴,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音毒涧,去河邊找鬼贮预。 笑死,一個(gè)胖子當(dāng)著我的面吹牛链嘀,可吹牛的內(nèi)容都是我干的萌狂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怀泊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼茫藏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起霹琼,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤务傲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后枣申,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體售葡,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年忠藤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了挟伙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡模孩,死狀恐怖尖阔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榨咐,我是刑警寧澤介却,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站块茁,受9級(jí)特大地震影響齿坷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜数焊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一永淌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧佩耳,春花似錦仰禀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至萍诱,卻和暖如春悬嗓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裕坊。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工包竹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人籍凝。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓周瞎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饵蒂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子声诸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容