【GAMS与C++的交互】

GAMS与C++的交互(版本要求:GAMS25.1最多支持VS2017,GAMS38可以支持VS2019)

若有侵权或者不恰当的使用,请及时联系作者
若起到了作用请一键三联
参考源代码(官方代码):
Tutorial (gams.com)

我的理解是,想要在C++里面运行GAMS程序,只需要把GAMS里面的数据和模型分别输入到函数中进行运行即可

  • C++输出到.gdx

    • 第一种方案:按照不同的分类格式一步一步地进行输出,这是官方的例程,使用的是string
    #include "gams.h"
    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <map>
    #include <cstdlib>
    
    using namespace gams;
    using namespace std;
    
    
    int main(int argc, char* argv[])
    {
    	cout << "---------- Transport GDX --------------" << endl;
    
    		GAMSWorkspaceInfo wsInfo;
    		if (argc > 1)
    			wsInfo.setSystemDirectory(argv[1]);
    		GAMSWorkspace ws(wsInfo);
    
    		// define some data by using C++ data structures
    		vector<string> plants = {
    			"Seattle", "San-Diego"
    		};
    		vector<string> markets = {
    			"New-York", "Chicago", "Topeka"
    		};
    		map<string, double> capacity = {
    			{ "Seattle", 350.0 }, { "San-Diego", 600.0 }
    		};
    		map<string, double> demand = {
    			{ "New-York", 325.0 }, { "Chicago", 300.0 }, { "Topeka", 275.0 }
    		};
    		map<tuple<string, string>, double> distance = {
    			{ make_tuple("Seattle", "New-York"), 2.5 },
    			{ make_tuple("Seattle", "Chicago"), 1.7 },
    			{ make_tuple("Seattle", "Topeka"), 1.8 },
    			{ make_tuple("San-Diego", "New-York"), 2.5 },
    			{ make_tuple("San-Diego", "Chicago"), 1.8 },
    			{ make_tuple("San-Diego", "Topeka"), 1.4 }
    		};
    
    		// create new GAMSDatabase instance
    		GAMSDatabase db = ws.addDatabase();
    
    		//C++----->gdx
    		// 这是将string格式的打上标签(添加成集合,集合名为canning plants)
    		// add 1-dimensional set 'i' with explanatory text 'canning plants' to the GAMSDatabase
    		GAMSSet i = db.addSet("i", 1, "canning plants");
    		for (string p : plants)
    			i.addRecord(p);
    
    		// add 1-dimensional set 'j' with explanatory text 'markets' to the GAMSDatabase
    		GAMSSet j = db.addSet("j", 1, "markets");
    		for (string m : markets)
    			j.addRecord(m);
    
    		//添加一维parameter的方式(并且可以加上使用的是什么集合)
    		// add parameter 'a' with domain 'i'
    		GAMSParameter a = db.addParameter("a", "capacity of plant i in cases", i);
    		for (string p : plants)
    			a.addRecord(p).setValue(capacity[p]);
    
    		//添加二维parameter的方式,之前也说过table是二维parameter的一种特殊形式
    		// add parameter 'd' with domains 'i' and 'j'
    		GAMSParameter d = db.addParameter("d", "distance in thousands of miles", i, j);
    		for (auto t : distance)
    			d.addRecord(get<0>(t.first), get<1>(t.first)).setValue(t.second);
    
    		//添加scaler
    		// add scalar 'f'
    		GAMSParameter f = db.addParameter("f", "freight in dollars per case per thousand miles");
    		f.addRecord().setValue(90);
    
    		//输出gdx文件,路径我喜欢绝对路径(这里的规则就是普通的C++的规则)
    		// export the GAMSDatabase to a GDX file with name 'data.gdx' located in the 'workingDirectory' of the GAMSWorkspace
    		db.doExport("C:\\Users\\henry\\Desktop\\data.gdx");
    
    		cout << "Content of GDX file 'data.gdx':";
    
    		// add a new GAMSDatabase and initialize it from the GDX file just created
    		GAMSDatabase db2 = ws.addDatabaseFromGDX("C:\\Users\\henry\\Desktop\\data.gdx");
    
    
    		//gdx------->c++
    
    		//读取我们先定义一个同格式的进行读取
    		// read data from symbols into C++ data structures
    		vector<string> iNew;
    		for (GAMSSetRecord rec : db2.getSet("i"))
    			iNew.push_back(rec.key(0));
    
    		vector<string> jNew;
    		for (GAMSSetRecord rec : db2.getSet("j"))
    			jNew.push_back(rec.key(0));
    
    		map<string, double> aNew;
    		for (GAMSParameterRecord rec : db2.getParameter("a"))
    			aNew[rec.key(0)] = rec.value();
    
    		map<tuple<string, string>, double> dNew;
    		for (GAMSParameterRecord rec : db2.getParameter("d"))
    			dNew[make_tuple(rec.key(0), rec.key(1))] = rec.value();
    
    		double fNew = db2.getParameter("f").firstRecord().value();
    
    		cout << "i:" << endl;
    		for (string s : iNew)
    			cout << "  " << s << endl;
    		cout << "j:" << endl;
    		for (string s : jNew)
    			cout << "  " << s << endl;
    		cout << "a:" << endl;
    		for (auto rec : aNew)
    			cout << "  " << rec.first << " : " << rec.second << endl;
    		cout << "d:" << endl;
    		for (auto rec : dNew)
    			cout << "  " << get<0>(rec.first) << ", " << get<1>(rec.first) << " : " << rec.second << endl;
    		cout << "f:" << endl;
    		cout << "  " << fNew;
    
    	return 0;
    }
    
    • 尝试了一下使用数组设置set,发现并不可行,查了一下函数定义,发现成员为string,gams里面这个问题同样存在
    GAMSSetRecord addRecord();
    GAMSSetRecord addRecord(const std::string& key1);
    GAMSSetRecord addRecord(const std::string& key1, const std::string& key2);
    GAMSSetRecord addRecord(const std::string& key1, const std::string& key2, const std::string& key3);
    

    解决方案,直接强制类型转换直接使用to_string()将int转化成string,如果嫌麻烦的话,可以对函数进行重载,就在头文件里复制一下加一行就可以了

    //写的部分
    //我来试试用数组的形式行不行,随便定义一组数据
    		double load[24] = { 0.0196,0.0186,0.0189,0.0202,0.0170,0.0767,0.0773,0.0889,0.2141,0.1255,0.0822,0.0558,0.340,0.0311,0.0266,0.0757,0.1181,0.1306,0.0639,0.0767,0.0735,0.0414,0.0286,0.0552 };
    		// 先来定义一个集合set
    		GAMSSet hour = db.addSet("hour", 1, "time scalar");
    		for (int o = 1; o < 25; o++)
    			hour.addRecord(to_string(o));
    		GAMSParameter load_gams = db.addParameter("load", "load of system", hour);
    		for (int o = 1; o < 25; o++)
    			load_gams.addRecord(to_string(o)).setValue(load[o-1]);
    //读的部分
    	vector<string> read_hour;
    		for (GAMSSetRecord rec : db2.getSet("hour"))
    			read_hour.push_back(rec.key(0));
    
    		map<string, double> load_new;
    		for (GAMSParameterRecord rec : db2.getParameter("load"))
    			load_new[rec.key(0)] = rec.value();
    
    • 第二种方案,使用string一口气进行传输:使用GAMSJob这个类
    1. 写入.gdx文件

      // 输入数据的格式
      string getDataText()
      {
      	return "Sets                                                           \n"
      		"  i   canning plants   / seattle, san-diego /                  \n"
      		"  j   markets          / new-york, chicago, topeka / ;         \n"
      		"Parameters                                                     \n"
      		"                                                               \n"
      		"  a(i)  capacity of plant i in cases                           \n"
      		"                     /    seattle     350                      \n"
      		"                          san-diego   600  /                   \n"
      		"                                                               \n"
      		"  b(j)  demand at market j in cases                            \n"
      		"                     /    new-york    325                      \n"
      		"                          chicago     300                      \n"
      		"                          topeka      275  / ;                 \n"
      		"                                                               \n"
      		"Table d(i,j)  distance in thousands of miles                   \n"
      		"               new-york       chicago      topeka              \n"
      		"  seattle          2.5           1.7          1.8              \n"
      		"  san-diego        2.5           1.8          1.4  ;           \n"
      		"                                                               \n"
      		"Scalar f  freight in dollars per case per thousand miles  /90/;\n";
      }
      //如果需要用C++写入GAMS的东西,直接将GAMS里面的内容用string按GAMS的格式写出来输入就可以
      	GAMSJob t3 = ws.addJobFromString(getDataText());
      	t3.run();
      	//TODO: change doExport to export?
      	t3.outDB().doExport("C:\\Users\\henry\\Desktop\\tdata.gdx");
      
    2. 读取我还没搞明白,后续可能会更新

      (但是我觉得用不上,因为读取完全可以通过gams读取gdx文件在gams里面计算,没必要使用C++调库求解)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值