跳轉到內容

GLPK/ODBC

來自華夏公益教科書,開放的書籍,為開放的世界

開放式資料庫連線 (ODBC) 為關係型資料庫管理系統提供標準化介面。GLPK 使用 ODBC 介面與關係型資料庫電子表格進行通訊,這些資料庫和電子表格包含執行時最佳化模型資料。

ODBC 需要安裝的驅動程式管理器 *和* 資料庫特定的 ODBC 連線。

官方文件

[編輯 | 編輯原始碼]

官方 GLPK 文件檔案中doc/gmpl.pdf包含了關於從關係型資料庫和電子表格使用表格的 *完整參考* (GLPK 4.27 - 4.44:參見doc/tables.pdf)。因此,此處不會重複大部分內容。請參閱獲取 GLPK

表格語句

[編輯 | 編輯原始碼]

使用表格語句來訪問特定的 ODBC 資料庫

table name alias IN 'ODBC' conn sql . . . sql :
set <- [ fld , . . . , fld ] , par ~ fld , . . . , par ~ fld ;

table name alias domain OUT 'ODBC' conn sql . . . sql :
expr ~ fld , . . . , expr ~ fld ;

100 字元限制

[編輯 | 編輯原始碼]

根據當前的程式設計,GMPL 中的字串限制為 100 個字元。此限制很容易在表格語句中達到,無論是

  • 連線字串 (conn) 語句,還是
  • SQL (sql) 語句。

一種解決方案是使用資料集名稱 (DSN) 連線字串,只包含密碼和使用者詳細資訊

'DSN=glpk;UID=glpk;PWD=gnu'

如果這不夠靈活,可以使用檔案 DSN(見後文)。

SQL 語句可以分佈在多行。SQL 語句最後一行最後一個字元必須是分號 (;)。各個字串用空格隔開,在傳送到 SQL 命令處理器之前進行連線。例如

 table ta {(i, j) in {i1 in 1..9} cross {i2 in 1..9}} OUT
   'ODBC' 'DSN=glpk;UID=glpk;PWD=gnu'
   'DELETE FROM sudoku_solution' # line 1 of SQL statement 1
   'WHERE ID = ' & id & ';'      # line 2 of SQL statement 1
   'INSERT INTO sudoku_solution' # line 1 of SQL statement 2
   '(ID, COL, LIN, VAL)'         # line 2 of SQL statement 2
   'VALUES(?, ?, ?, ?);' :       # line 3 of SQL statement 2
   id ~ ID, i ~ COL, j ~ LIN, (sum{k in 1..9} x[i,j,k] * k) ~ VAL;

自定義構建

[編輯 | 編輯原始碼]

可以安全地增加MAX_LENGTH檔案中的宏src/glpmpl.h從 100 到 240,以允許處理更長的符號值,包括傳遞給 ODBC 驅動程式的控制字串。缺點是,您的模型可能不再適用於 GLPK 的預設構建。這個問題也在這個2012 年初的帖子中討論。

MySQL 支援

[編輯 | 編輯原始碼]

GLPK 原始碼構建

[編輯 | 編輯原始碼]

GLPK 的預設構建*沒有*啟用MySQL 表驅動程式。要使用此資料庫,您需要按如下方式配置 GLPK

./configure --enable-dl --enable-mysql ...

然後執行make像往常一樣。如果您嘗試在沒有此支援的情況下訪問 MySQL,GLPK 將報告

MySQL table driver not supported

GLPK Windows 7 可執行檔案

[編輯 | 編輯原始碼]

如果您執行的是 64 位 Windows 7,並且希望使用 GLPSOL 可執行檔案從MySQL 資料庫中提取資料,解決您在 MathProg 中的問題.mod檔案,然後將解決方案寫回您的資料庫,請嘗試以下操作(已確認 2011 年 9 月使用 GLPK 4.47)。您首先需要

  • 64 位 MySQL Community Server 5.5.16 for Windows (x86, 64 位) — 下載
  • 64 位 MySQL ODBC Connector 5.1.8 for Windows (x86, 64 位) — 下載
  • 64 位 GLPK 可執行檔案 — 請參閱獲取Windows 可執行檔案

使用以下方法設定 64 位資料來源c:\Windows\system32\odbcad32.exe如以下所述,訪問您的 MySQL 資料庫存。

以下 MathProg 程式碼展示了一種在您的模型中填充 MathProg *集* 的方法

/* Import finished goods set from MySQL database */

table t IN "iODBC"
   'DSN=glpk;UID=glpk;PWD=glpk'
   'export_finished_good' :
   FIN <- [ FinishedGood ];

在上面的例子中,export_finished_goodFinishedGood分別是來自 MySQL 資料庫的相關表名和欄位名。以及FIN是您想要用資料庫中的資料填充的 MathProg 集。

以下 MathProg 程式碼展示了一種在您的模型中填充二維 MathProg *陣列* 的方法

/* Import finished good demand from MySQL database */

table t IN "iODBC"
   'DSN=glpk;UID=glpk;PWD=glpk'
   'export_finished_good_demand' :
   [ FinishedGood, PERIOD ], FinDem ~ DEMAND;

在此示例中,讀取了每個時期特定商品的需求。資料來自 MySQL 表export_finished_good_demand並用於填充 MathProg 陣列FinDem,其維度由FINTIM決定 - 它們分別表示成品和時間段的兩個集合。儲存成品列表的欄位名為FinishedGood,儲存時間段列表的欄位名為PERIOD,儲存每個時期每個成品需求的欄位名為DEMAND。接收此資料的 MathProg 陣列之前宣告為FinDem{FIN, TIM}.

安裝 ODBC 驅動程式管理器

[編輯 | 編輯原始碼]

ODBC 是Windows 的組成部分。對於Linux,兩個開源專案提供了 ODBC API 的主要實現

ODBC 聯結器使用的庫儲存在配置檔案中/etc/odbcinst.ini。例如,如果在 Linux 上使用MySQL 關係型資料庫管理系統

[MySQL]
Description     = ODBC for MySQL
Driver          = /usr/lib/odbc/libmyodbc.so
Setup           = /usr/lib/odbc/libodbcmyS.so
UsageCount      = 1
CPTimeout       =
CPReuse         =

Windows 在登錄檔項下儲存相同的資訊HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI.

設定 DSN

[編輯 | 編輯原始碼]

資料集名稱 (DSN) 是描述關係型資料庫訪問資料的結構。存在三種類型的 DSN

  • 系統 DSN — 儲存在/etc/odbc.ini在 Linux 下,或在 Windows 登錄檔項中HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI
  • 使用者 DSN — 儲存在~/.odbc.ini在 Linux 下,或在 Windows 登錄檔項中HKEY_CURRENT_USER\Software\ODBC\ODBC.INI
  • 檔案 DSN

iODBC 和 unixODBC 在 Linux 下提供 DSN 編輯器。

如果使用 32 位 Windows,請呼叫c:\WINDOWS\system32\odbcad32.exe用於編輯資料來源。如果使用 64 位 Windows,則可以存在 32 位和 64 位資料來源。要編輯 64 位資料來源,請呼叫c:\WINDOWS\system32\odbcad32.exe,要編輯 32 位資料來源,請呼叫c:\WINDOWS\syswow64\odbcad32.exe.

檔案 DSN 在單個檔案中儲存單個 DSN 的描述,例如

[ODBC]
DRIVER=Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
DBQ=.\sudoku.xlsx

對於檔案 DSN,Windows 預設情況下使用路徑c:\Program Files\Common Files\ODBC\Data Sources.

DSN 中的密碼未加密,因此出於安全原因,*不要將* DSN 資訊儲存在不安全的機器上。

連線字串

[編輯 | 編輯原始碼]

使用 ODBC 介面的應用程式必須將資料庫連線的訪問資料作為連線字串傳遞給 ODBC API。

連線字串可以*可選地*引用 DSN,在*覆蓋*過程中覆蓋某些(或全部)欄位。

以下連線字串引用名為glpk的 DSN,並覆蓋當前使用者名稱和密碼

DSN=glpk;UID=myuser;PWD=mypassword

以下連線字串在應用程式路徑內使用檔案 DSN

FileDSN=.\sudoku_excel.dsn

無 DSN 連線字串指定驅動程式和驅動程式特定的引數,例如

DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb);DBQ=.\sudoku.xlsx

Microsoft Access

[編輯 | 編輯原始碼]

Microsoft Access 是微軟辦公套件中的一部分,它是一個關係型資料庫應用程式。 Access 的驅動程式包含在可下載的“2007 Office System Driver: Data Connectivity Components”和“Microsoft Access Database Engine 2010 Redistributable”資源中。

對於 Access 2007 和 2010,一個有效的無 DSN 連線字串的示例是

DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};dbq=.\glpk.accdb

對於早期版本的 Access,一個有效的無 DSN 連線字串的示例是

DRIVER={Microsoft Access Driver (*.mdb)};dbq=.\glpk.mdb

機器架構

[edit | edit source]

Microsoft Access 2007 是一個 32 位應用程式,如果您希望使用 ODBC 連線到 Access,則必須使用 32 位版本的 GLPK。 如果您需要使用 64 位版本的 GLPK,那麼您需要安裝 Access 的 64 位 ODBC 聯結器。 它包含在 64 位版本的“Microsoft Access Database Engine 2010 Redistributable”或 64 位版本的 Microsoft Office 2010 中。 Microsoft Office 的 32 位和 64 位安裝是互斥的——如果您想使用 64 位 Access,則需要刪除 32 位 Access。

SQL 語法

[edit | edit source]

以下 SQL 語法適用於編寫與 Access 互動的 GMPL 模型

  • 字串必須用撇號括起來(例如'Value'),而不是用引號括起來(例如"Value")
  • 要將 DateTime(時間戳)欄位轉換為 GLPK 使用的時間表示形式,請呼叫 Access 函式 DateDiff [1]
  • 列別名不能是保留名稱,例如 time
  • 包含空格的列名必須用方括號括起來(例如[Product Code]).

例如

set ProdTime, dimen 2;
param sales{ProdTime};
table products_table IN "ODBC"
  'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};dbq=.\sales.accdb'
  'SELECT'
  '  [Product Code] AS p,'
  '  DateDiff(''s'', #01/01/1970#, Period) AS t,'
  '  [Net Sales] AS s'
  'FROM [Historic Sales]'
  'WHERE [Product Text] = ''Unskimmed Milk'';' :
  ProdTime <- [p, t], sales ~ s;

可以在 [2] 中找到 Access 2007 函式列表。

Microsoft Excel

[edit | edit source]

Microsoft Excel 是微軟提供的電子表格程式。 Excel 的驅動程式包含在可下載的“2007 Office System Driver: Data Connectivity Components”和“Microsoft Access Database Engine 2010 Redistributable”資源中。“Microsoft Access Database Engine 2010 Redistributable”資源包含 32 位和 64 位版本。 使用與您擁有的 GLPK 庫匹配的版本。

以下連線字串使用檔案無 DSN 連線到 Microsoft Excel

DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb);DBQ=.\sudoku.xlsx;READONLY=FALSE

預設情況下,對 Excel 的 ODBC 連線是隻讀的。 [3] 您必須設定ReadOnlyFalse才能將資料寫回 Excel。

Excel ODBC 驅動程式不支援 DELETE、UPDATE 或 ALTER TABLE 語句。 [4]。 本質上,它只能追加新行。

以下欄位受支援

欄位 意義
驅動程式 ODBC 連線驅動程式 
DBQ Excel 檔名
FirstRowHasNames  1 = true,0 = false
ReadOnly False = 可寫入

在下面的示例中,集合 'orders' 的條目被寫入 Excel 工作簿中名為 'result' 的區域out.xlsx。 為了使示例能夠正常工作,Excel 工作簿out.xlsx必須存在,並且必須包含一個名為 'result' 的命名區域,該區域包含 3 列。

param tableName, symbolic;
set orders, dimen 3;
solve;
table result {(p, o, q) in orders} OUT "ODBC" 
  'DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};' &
  'DBQ=.\out.xlsx;READONLY=FALSE'
  'DROP TABLE [' & tableName & '];'
  'CREATE TABLE [' & tableName & ']'
  '(Product CHAR(20), OrderNumber CHAR(10), Quantity DOUBLE);'
  'INSERT INTO  [' & tableName & ']'
  '(Product, OrderNumber, Quantity)'
  'VALUES(?, ?, ?);' :
  p, o, q;
data;
param tableName := 'result';
set orders :=
  'Full Milk',         '0600000101', 10.,
  'UHT Milk',          '0600000102', 16.,
  'Semi Skimmed Milk', '0600000103', 14.,
  'UHT Milk',          '0600000104', 36.;
end;

有關更多資訊,請在 "Excel" 上搜索help-glpk郵件列表。

執行一系列不寫入記錄的 SQL 語句

[edit | edit source]

您可能希望執行一個或多個不寫入記錄的 SQL 語句。 例如,您可能希望從表中刪除所有記錄。 這可能很棘手,因為如果最後一行包含“?”,GMPL 將假設它命名了一個表,並執行一個多餘的 INSERT INTO。 一個解決方法是在最後一個語句中編碼一個不必要的“?”。 例如

 table DeleteRecords {x in 1..1} OUT
   'ODBC' 'DSN=glpk;UID=glpk;PWD=gnu'
   'DELETE FROM sudoku_solution WHERE ?=?' :
   x, x;

ODBC 陷阱

[edit | edit source]

如果要從資料庫讀取浮點資料,GLPSOL 只能在資料包含一個點“.”作為小數點分隔符時才能處理它。 因此,ODBC 驅動程式必須確保以這種格式返回資料。 在 Oracle 11g 資料庫的情況下,將環境變數 NLS_LANG 設定為“American_America.WE8ISO8859P1”,然後資料庫將返回“.”作為數字資料的十進位制分隔符(ODBC 驅動程式讀取該變數並相應地格式化資料)。

在 SELECT 語句中使用“*”必須謹慎處理。 GMPL 需要在 SQL 語句中具有與 GMPL 表語句中引用的完全相同的列名。 SQL 列與 GMPL 欄位名稱之間沒有自動匹配。

根據 SQL 實現和作業系統,列名可能區分大小寫。 [5].

參考文獻

[edit | edit source]
  1. "DateDiff Function". Microsoft Corporation. Retrieved 26 June 2011.
  2. "Access 2007 Help and How-to - Macros and programmability - Functions (alphabetical)". Microsoft Corporation. Retrieved 26 June 2011.
  3. "257819 How To Use ADO with Excel Data from Visual Basic or VBA". Microsoft Corporation. Retrieved 28 December 2010.
  4. "INF: Excel ODBC Driver and Text ODBC Driver Notes". Retrieved 30 May 2013.
  5. "Identifier Case Sensitivity". Oracle. Retrieved 2012-02-27.
華夏公益教科書