天天看點

LINGO調用VC編寫的函數動态庫實驗

Visual C++編寫函數,然後用動态庫的形式輸出該函數供LINGO調用. 某公司生産A,B和C三種産品,售價分别是12元、7元和6元.生産每件A産品需要1小時技術服務、10小時直接勞動、3千克材料;生産每件B産品需要2小時技術服務、4小時直接勞動、2千克材料;生産每件C産品需要1小時技術服務、5小時直接勞動、1千克材料.現在最多能提供100小時技術服務、700小時直接勞動、 400千克材料.生産成本是非線性函數,如下表.要求建立一個總利潤最大的數學模型.

産品A (件) 成本 (元/件) 産品B (件) 成本 (元/件) 産品C (件) 成本 (元/件)
0~40 41~100 101~ 150 150以上 10 9 8 7 0~50 51~100 100以上 6 4 3 0~100 100以上 5 4

設生産産品Ax1件,生産産品Bx2件生産産品Cx3 件.問題的難點是産品的成本是一個分段函數,難以用線性函數表達,是以可采用動态庫編寫一個專門的函數來計算成本. 設産品A每件的成本為a元,産品B每件的成本為b元,産品C每件的成本為c元。a、b、c随 x1,x2,x3而改變 目标函數為:

maxZ=12x1+7x2+6x3-(ax1+bx2+cx3);

a、b、c為分段函數。 由于目标函數是非線性的,且難以用一個式子表達,是以采用自己編寫庫函數的方式來實作。這裡介紹@USER函數。該函數允許使用者自己編寫函數,該函數允許使用者自己編寫函數,該函數應當用C或FORTRAN語言編寫,傳回值為使用者計算的結果. @USER函數包含兩個參數:第一個用于指定參數的 個數,第二個用于指定 參數向量(類似于C語言中的main(argc,argv)的編寫格式).在LINGO中調用USER時則直接指定對應的參數(類似C語言中的main(argc,argv)的執行格式). 該函數采用動态庫編寫.這裡的例子采用VC編寫動态庫.注意動态庫中 該函數名固定為MYUSER,在LINGO中調用時則 固定外部函數名為USER. 過程如下, 啟動VC,建立動态連結庫項目,選擇空的dll工程,也即預設選項。

LINGO調用VC編寫的函數動态庫實驗

Project->Add to Project->New.選擇Files頁面,C++ SourceFile,輸入檔案名比如CB。

LINGO調用VC編寫的函數動态庫實驗

CB.cpp内容 程式中MYUSER函數的第一個整型變量NumArgs代表輸入變量的個數。 第二個輸入為向量x,也就是外部輸入的變量。 第三個變量dResult用于傳回最後的計算結果。 用LINGO調用時隻需輸入各變量就行了,函數自動傳回C++程式計算的結果dResult。(是不是說隻能有一個傳回值???而不是傳回結果向量??)

#include <WINDOWS.H>
#include <string.h>
#include <stdio.h>
#include <STDLIB.H>
#include <MATH.H>
#define N 3
#define DllExport extern "C" _declspec(dllexport)//導出函數
//該函數計算成本
DllExport void MYUSER(int* NumArgs,double *x,double *dResult)
{
	double sum;
	if (*NumArgs<N)
	{
		MessageBox(NULL,"輸入變量不足","輸入錯誤",MB_OK);
		*dResult=-1;
		exit(0);

	}
	sum=0;
	//産品A的成本計算
	if (x[0]>=0 && x[0]<=40)
	{
		sum+=10*x[0];
	}
	else if (x[0]>=41 && x[0]<=100)//原書錯誤為x[1]
	{
		sum+=9*x[0];
	}
	else if (x[0]>=101 && x[0]<=150)
	{
		sum+=8*x[0];
	}
	else 
		sum+=7*x[0];

	//産品B的成本計算
	if (x[1]>=0 && x[1]<=50)
	{
		sum+=6*x[1];
	}
	else if (x[1]>=51 && x[1]<=100)
	{
		sum+=4*x[1];
	}
	else 
	{
		sum+=3*x[1];
	}

	//産品C的成本計算
	if (x[2]>=0 && x[2]<=100)
	{
		sum+=5*x[2];
	}
	else 
	{
		sum+=4*x[2];
	}
	*dResult=sum;//傳回成本總值
	
}
           

按F7運作後生成動态庫CALC.DLL,将其拷貝到LINGO目錄下,并将檔案改名為MYUSER.DLL。啟動LINGO就可以通過外部函數@USER調用動态庫中自己編寫的函數。

Lingo模型

!采用動态庫編寫自己的函數;
MODEL:
max=12*x1+7*x2+6*[email protected](x1,x2,x3);!目标函數;
x1+2*x2+x3<=100;!技術服務的限制;
10*x1+4*x2+5*x3<=700;!直接勞動的限制;
3*x1+2*x2+x3<=400;!材料的限制;
@GIN(x1);
@GIN(x2);
@GIN(x3);
END
           

結果

  Local optimal solution found.

  Objective value:                              263.0000

  Objective bound:                              263.0000

  Infeasibilities:                             0.5000000E-06

  Extended solver steps:                               2

  Total solver iterations:                          7231

                       Variable           Value        Reduced Cost

                             X1        41.00000           -4.500000

                             X2        1.000000            0.000000

                             X3        57.00000          -0.5000001

                            Row    Slack or Surplus      Dual Price

                              1        263.0000            1.000000

                              2        0.000000           0.5000000

                              3        1.000002            0.000000

                              4        218.0000            0.000000

繼續閱讀