Matlab中的遗传算法能否将适应度函数的第二个返回值传递给约束?

时间:2014-03-21 12:32:48

标签: matlab mathematical-optimization genetic-algorithm

我在Matlab中模拟批量蒸发器。遗传算法改变了几个起始变量x(例如尺寸,工作流体的最大质量,所用蒸发器的总数......),目标是最大化效率。所以我的函数evaporator(x)返回了由算法最小化的负效率 除了效率之外,还计算了其他几个值。一个是模拟周期的持续时间(不是计算本身的运行时间!)。作为约束,整个蒸发周期的持续时间应取决于蒸发器的数量,不应短(例如,如果使用三个蒸发器,整个循环应至少需要3 * 5s = 15s)。 我知道我可以轻松使用ga(nonlcon)的非线性约束选项。在这种情况下,我只需要再次从evaporator(x)进行相同的计算,但这次返回计算的持续时间。问题是,每次运行我必须调用几千次外部DLL并且计算变得非常慢。因此,我真的想避免两次运行所有计算 在某种程度上可能,evaporator(x)同时返回负效率和持续时间吗?然后ga应该最小化负效率并评估关于约束的持续时间。我想过将evaporator(x)嵌套在一个匿名函数中,但我认为我的函数仍然需要被调用两次呢?

我在效率和持续时间的多目标优化方面有很好的经验,但不幸的是gamultiobj算法无法处理整数变量。

目前我在evaporator(x)内的短暂持续时间内使用惩罚函数,但我认为,ga算法的约束处理会比这更好。

修改 所以它有点复杂,但最终它正在起作用:

function [ returnValue ] = switchHXoutput( requestedCase, inputs )
%SwitchHXoutput returns fitness value or duration depending on requested
%case

persistent fitnessValue duration oldInputs;

if isempty(oldInputs)
    oldInputs = {}; %initialize oldInputs as cell
end


[isAllreadyCalculated, iOldInput] =...
ismember(cell2mat(inputs), cell2mat([oldInputs{:}]), 'rows'); 

if isempty(oldInputs) || ~isAllreadyCalculated
    [fitnessValue(end+1), duration(end+1)] = lengthyCalculation(inputs); %add current results to persistent array
    oldInputs(end+1) = {inputs}; %add current inputs to persistent array
    returnValue = [fitnessValue(end), duration(end)];
else
    returnValue = [fitnessValue(iOldInput), duration(iOldInput)]; % return old values
end

if strcmp(requestedCase, 'FitnessValue')
    returnValue = returnValue(1);
elseif strcmp(requestedCase, 'duration')
    returnValue = returnValue(2);
else
    error('MyApp:SelectOutput','Requested case not supported')
end

end %function

我知道不断增长的细胞阵列并不是很快。但由于我的lengthyCalculation每次通话大约需要2分钟,我仍然可以节省很多时间。此外,每一代中最好的人都会在下一代中再次使用。因此,在这种情况下,可以使用保存的值,而不是再次重新计算它们。该代码也适用于并行计算。通常,适合度值和持续时间由同一工人计算。只有后代才有结果可以在另一个工人身上。

1 个答案:

答案 0 :(得分:1)

一个选项是包含一些持久状态,它记录上次运行时计算的效率和持续时间(这是 memoization ),并根据函数输入决定返回哪个。

例如,

function return_value = evaporator(method, value, inputs)

  persistent efficiency duration;

  if strcmp(method, 'recalculate')
      % Some lengthy calculation goes here
      efficiency = inputs + 1;
      duration   = inputs + 10;
      pause(5);
  end

  switch value
    case 'efficiency'
      return_value = efficiency;
    case 'duration'
      return_value = duration;
  end

end

结果是

>> evaporator('recalculate', 'efficiency', 10)
11
>> evaporator('memoized', 'duration')
20
>> evaporator('recalculate', 'efficiency', 20)
21
>> evaporator('memoized', 'duration')
30