【问题标题】:c callbacks functions for numerical optimization用于数值优化的 c 回调函数
【发布时间】:2012-06-14 12:54:23
【问题描述】:

我的应用程序库需要调用优化例程:

 err = optim(int n, double *x, double *f, void *obj)

然后例程将调用目标函数来请求目标函数值。

 void obj(int n, double *x, double *f)

optim() 是外部库的一部分。 optim() 和 obj() 的签名是固定的。

函数obj() 需要访问包含在单个对象“模型”中的数据。所有其他函数都传递指向模型对象的指针。因此,运行优化器的调用可能类似于:

 err = doOptimize(model)

doOptimize() 将设置问题并致电optim()

 err= optim(model->n, model->x, model->f, model->obj)

问题是,除了nxf 之外,obj() 函数能否访问驻留在model 对象中的变量? obj() 函数需要调用其他需要 model 对象来进行实际计算的函数:

    updateParms(model);
    computeF(model);

我不确定obj() 在没有实际句柄的情况下如何进行这些调用?以下可以工作吗?

    updateParms();
    computeF();      

谢谢,

【问题讨论】:

  • 您是指nxf 成员以外的数据吗?您能否提供更详细的代码示例,并准确说明您要做什么?

标签: c optimization callback scope nested-function


【解决方案1】:

由于您无法修改optim()obj() 的签名,您需要创建一个中间步骤来执行对obj() 函数的真正调用。根据需要一次进行多少次优化调用,这可以像保存模型指针的全局/静态变量一样简单,例如:

void obj(struct model *m, int n, double *x, double *f)
{
    /* Access to all information here */
}

static struct model *optim_model;

void obj_caller(int n, double *x, double *f)
{
    obj(optim_model, n, x, f);
}

int doOptimize(struct model *m)
{
    optim_model = m;
    return optim(m->n, m->x, m->f, obj_caller);
}

或者,如果您需要更高级或不喜欢使用单个全局,并且可以使用 n 参数作为标识符,您可以使用该标识符来调用多个优化模型:

void obj(struct model *m, int n, double *x, double *f)
{
    /* Access to all information here */
}

#define MAX_MODELS (10)
static struct model *optim_models[MAX_MODELS] = {0};

void obj_caller(int n, double *x, double *f)
{
    for (int i = 0; i < MAX_MODELS; i++)
    {
        if (optim_models[i]->n == n)
        {
            obj(optim_models[i], n, x, f);
            break;
        }
    }
}

int doOptimize(struct model *m)
{
    return optim(m->n, m->x, m->f, obj_caller);
}

int main(void)
{
    struct model m1;
    struct model m2;

    m1.n = 1;
    optim_models[0] = &m1;

    m2.n = 2;
    optim_models[1] = &m1;

    int err = doOptimize(&m2);
}

如果需要,我相信您可以找到一种更合适的方法来存储多个模型,例如具有真实标识符的链表。

【讨论】:

    【解决方案2】:

    是的,也不是。

    当然,您的函数obj 可以像访问任何其他内存一样访问模型,但我没有看到任何机制让它知道model 的地址。

    您需要向obj 添加另一个参数,用于传递model 指针。

    在 C++ 中,您可能会通过使 obj 成为 Class Model 的“成员”来做到这一点。然后编译器将添加一个名为this 的隐藏参数(它为所有成员函数执行此操作),其中包含指向对象实例“模型”的指针。如果你想在纯 C 中实现同样的效果,那么你必须传递你自己的 this 指针(但你可以随意调用它)。

    所以,是这样的:

    ... doOptimize (... model)
    {
      ....
      optim (model->n, model->x, model->x, model)
      ....
    }
    
    ... optim (int n, double *x, double *f, ... model)
    {
      ....
      model->obj (n, x, f, model);
      ....
    }
    
    void obj (int n, double *x, double *f, ... model)
    {
       /* use n, x, and f */
       /* use model->stuff */
    }
    

    当然,如果您总是使用相同的nxf,那么您只需传递model

    顺便说一句,不要将void * 用作函数指针:这不是一个好主意。

    【讨论】:

    • 您的解决方案比我的描述更能描述问题。 optim() 是外部库的一部分。 optim() 和 obj() 的签名是固定的。我无法按照建议提出问题这一事实激发了这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多