我在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分钟,我仍然可以节省很多时间。此外,每一代中最好的人都会在下一代中再次使用。因此,在这种情况下,可以使用保存的值,而不是再次重新计算它们。该代码也适用于并行计算。通常,适合度值和持续时间由同一工人计算。只有后代才有结果可以在另一个工人身上。
答案 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