跳转到内容

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() 方法。这些可以在终端或回调监听器中调用。

华夏公益教科书