这个优化问题的主要挑战是数学性质的。从你对
gen_abc
方法的定义中可以推断出,你的目标是通过找到各种变量(如
$a
、
$b
等)的边界区间来削减搜索空间。
最佳策略是从完整约束集中提取尽可能多的
线性约束条件,尝试使用
线性规划技术推断出边界,然后针对修剪后的变量空间进行详尽(或非确定性)的试错测试。
一个典型的
线性规划问题的形式为:
minimize (maximize) <something>
subject to <constraints>
例如,给定三个变量
a
、
b
和
c
,以及以下线性约束条件:
<<linear_constraints>>::
$a < $b
$b > $c
$a > 0
$c < 30
你可以按照以下方式找到
$a
、
$b
和
$c
的上下限:
lower_bound_$a = minimize $a subject to <<linear_constraints>>
upper_bound_$a = maximize $a subject to <<linear_constraints>>
lower_bound_$b = minimize $b subject to <<linear_constraints>>
upper_bound_$b = maximize $b subject to <<linear_constraints>>
lower_bound_$c = minimize $c subject to <<linear_constraints>>
upper_bound_$c = maximize $c subject to <<linear_constraints>>
在Perl中,您可以使用
Math::LP来实现此目的。
例子
线性约束的形式为“C eqop C1×$V1 ± C2×$V2 ± C3×$V3 ...
”,其中
eqop
是<
,>
,==
,>=
,<=
中的一个
$V1
,$V2
等是变量,
C
,C1
,C2
等是常数,可能等于0。
例如,给定...
$a < $b
$b > $c
$a > 0
$c < 30
将所有变量(及其系数)移到不等式左侧,将孤立的常数移到不等式右侧:
$a - $b < 0
$b - $c > 0
$a > 0
$c < 30
我将为您翻译编程相关内容。请调整约束条件,仅使用=
、<=
和>=
(不等式),假设我们的变量是离散的即整数值:
- '... < C' 变成 '... <= C-1'
- '... > C' 变成 '... >= C+1'
也就是说,
$a - $b <= -1
$b - $c >= 1
$a >= 1
$c <= 29
...然后写出像这样的内容:
use Math::LP qw(:types);
use Math::LP::Constraint qw(:types);
my $lp = new Math::LP;
my $a = new Math::LP::Variable(name => 'a');
my $b = new Math::LP::Variable(name => 'b');
my $c = new Math::LP::Variable(name => 'c');
my $constr1 = new Math::LP::Constraint(
lhs => make Math::LP::LinearCombination($a, 1, $b, -1),
rhs => -1,
type => $LE,
);
$lp->add_constraint($constr1);
my $constr2 = new Math::LP::Constraint(
lhs => make Math::LP::LinearCombination($b, 1, $c, -1),
rhs => 1,
type => $GE,
);
$lp->add_constraint($constr2);
...
my $obj_fn_a = make Math::LP::LinearCombination($a,1);
my $min_a = $lp->minimize_for($obj_fn_a);
my $max_a = $lp->maximize_for($obj_fn_a);
my $obj_fn_b = make Math::LP::LinearCombination($b,1);
my $min_b = $lp->minimize_for($obj_fn_b);
my $max_b = $lp->maximize_for($obj_fn_b);
...
当然,以上内容可以推广到任意数量的变量V1
,V2
,...(例如$a
,$b
,$c
,$d
,...),使用任何系数C1
,C2
,...(例如-1,1,0,123等)和任何常量值C
(例如-1,1,30,29等),只要您能将约束表达式解析为相应的矩阵表示,例如:
V1 V2 V3 C
[ C11 C12 C13 <=> C1 ]
[ C21 C22 C23 <=> C2 ]
[ C31 C32 C33 <=> C3 ]
... ... ... ... ... ...
应用到您提供的例子,
$a $b $c C
[ 1 -1 0 <= -1 ] <= plug this into a Constraint + LinearCombination
[ 0 1 -1 >= 1 ] <= plug this into a Constraint + LinearCombination
[ 1 0 0 >= 1 ] <= plug this into a Constraint + LinearCombination
[ 0 0 1 <= 29 ] <= plug this into a Constraint + LinearCombination
注意
顺便提一下,如果进行非确定性(基于rand
)测试,则可能或可能不是一个好主意来跟踪已经测试过的($a,$b,$c)
元组(例如在哈希中),以避免再次测试它们,前提是只有:
- 被测试的方法比哈希查找更昂贵(这在您提供的示例代码中不适用,但在您的实际代码中可能是一个问题或不是问题)
- 哈希表不会变得非常庞大(所有变量都受有限区间的约束,其乘积是一个合理的数字 - 在这种情况下,检查哈希表大小可以指示您是否已完全探索了整个空间 - 或者您可以定期清除哈希表,以至少在一个时间间隔内进行一次冲突检测。)
- 最终,如果您认为以上内容适用于您,则可以计时各种实现选项(使用和不使用哈希表),并查看是否值得实施。