GLPK/錯誤處理
外觀
< GLPK
本頁描述了處理 GLPK 中故障狀態的策略——同時注意到預防通常比治療更好。
如果 GLPK 庫中發生執行時錯誤,預設情況下,GLPK 通常會釋放 GLPK 庫環境並中止呼叫程式。如果您希望防止呼叫程式被中止,則定義一個自定義錯誤處理函式並透過呼叫以下方法註冊該函式:glp_error_hook。您的處理函式應首先呼叫glp_free_env來釋放 GLPK 庫環境,然後應用longjmp來自 C 標準庫標頭檔案中的呼叫setjmp.h將控制權返回給呼叫程式。然後,呼叫程式可以採取適當的操作,這可能包括有序的退出和退出。
下面的示例說明了使用自定義錯誤處理函式(請注意一些註釋塊中的 Doxygen 標記)
/*
* This example file demonstrates how to safely treat errors when
* calling the glpk library.
*
* It creates a problem and alternatively adds 1 or -1 columns.
* Trying to add -1 columns will cause the GLPK library to error.
*/
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h> /* provides the longjmp function */
#include "glpk.h"
void errorHook(void *in);
void buildModel(int forceError);
#define INFO struct sinfo
struct sinfo {
char *text;
jmp_buf *env;
};
/*
* This is the main function.
*/
int main(int argc, char** argv) {
int i;
printf("GLPK version: %s\n", glp_version());
for (i = 1; i < 5; i++) {
printf ("\nIteration %d", i);
if (i & 1) {
printf(", error expected to occur.\n");
} else {
printf(", success expected.\n");
}
if (runOptimizer(i)) {
printf("An error has occured.\n");
} else {
printf("Successful execution.\n");
}
}
return (EXIT_SUCCESS);
}
/**
* This function secures calls to glpk with an error hook.
* @param forceError force error if bit 0 = 1
* @return ok code: 1 failure, 2 out of memory
*/
int runOptimizer(int forceError) {
int ret = 0;
INFO *info;
info = (INFO*) malloc(sizeof(INFO));
if (info == NULL) {
return 2;
}
info->env = (jmp_buf *) malloc(sizeof(jmp_buf));
if (info->env == NULL) {
free(info);
return 2;
}
info->text = "This information was passed to the hook function.";
if (setjmp(*(info->env))) {
printf("Post treatment of error.\n");
ret = 1;
} else {
glp_error_hook(errorHook, info);
buildModel(forceError);
}
glp_error_hook(NULL, NULL);
free(info->env);
free(info);
return ret;
}
/**
* Build a model with one column
* @param forceError force error if bit 0 = 1
*/
void buildModel(int forceError) {
glp_prob *lp;
/* create problem */
lp = glp_create_prob();
if (forceError & 1) {
/* add -1 column
* this will cause an error.
*/
glp_add_cols(lp, -1);
} else {
/* add 1 column */
glp_add_cols(lp, 1);
}
/* delete problem */
glp_delete_prob(lp);
}
/**
* This hook function will be called if an error occurs when
* calling the GLPK library.
*/
void errorHook(void *in) {
INFO *info;
info = (INFO *) in;
printf("%s\n",info->text);
/* free glpk memory */
glp_free_env();
/* safely return */
longjmp(*(info->env), 1);
}
使用者有時希望終止正在執行的命令列程式。這通常透過按 Ctrl-C 來實現,這會導致作業系統向活動程式傳送一個SIGINT訊號。
如果SIGINT沒有被程式捕獲和處理,系統會或多或少地立即終止程序。程式設計師通常希望提供一種更優雅的方法。GLPK 提供了glp_error_hook處理函式來實現此目的。如果您希望在求解器解決過程的中間終止求解器,只需從該處理函式中呼叫以下程式碼:
glp_error("%s\n", "Aborting due to user request");
如果 MIP 問題正在執行,您希望讓當前解完成,那麼使用
glp_ios_terminate(tree);
註冊處理函式的程式碼沒有在這裡給出,但您可以在 2011 年的 帖子 中找到更多詳細資訊。
在 GLPK for Java 中,GLPK 庫中的錯誤會導致 org.gnu.glpk.GlpkException 類的異常。提供了 GLPK.glp_java_error() 和 GLPK.glp_ios_terminate() 方法。這些可以在終端或回撥監聽器中呼叫。