Основная проблема в этой проблеме оптимизации носит математический характер.
Ваша цель, поскольку я могу сделать вывод из вашего определения метода gen_abc
, заключается в том, чтобы обрезать ваше пространство поиска, найдя ограничивающие интервалы для различных переменных ($a
, $b
и т. Д.)
Лучшая стратегия для извлечения столько линейных ограничений из вашего полного набора ограничений, попытка вывести границы (используя linear programming метод, см ниже), а затем приступить к исчерпывающему (или недетерминированы) Триал и-ошибки против обрезанного пространства переменных.
Типичный linear programming problem имеет вид:
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); # imports optimization types
use Math::LP::Constraint qw(:types); # imports constraint 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), # 1*$a -1*$b
rhs => -1,
type => $LE,
);
$lp->add_constraint($constr1);
my $constr2 = new Math::LP::Constraint(
lhs => make Math::LP::LinearCombination($b, 1, $c, -1), # 1*$b -1*$c
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);
...
# do exhaustive search over ranges for $a, $b, $c
Конечно, выше может быть обобщена на любое количество переменных V1
, V2
... (например, $a
, $b
, $c
, $d
, ...), с любым коэффициенты C1
,, ... (например, -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)
кортежи уже испытанной, чтобы избежать снова испытывать их, тогда и только тогда, когда:
- метод испытывается дороже хэш-поиска (это не так с кодом примера, который вы указали выше, но может или не может быть проблемой с вашим реальным кодом)
- хэш не будет расти до огромных размеров (либо все переменные связаны конечными интервалами, продукт которых является разумным числом - в в каком случае проверка размера хэша может указывать, полностью ли вы изучили все пространство или нет, или вы можете периодически очищать хэш, так что, по крайней мере, за один временной интервал в то время, когда у вас есть некоторое столкновение det ection.)
- В конечном счете, если вы считаете, что вышеуказанное может применяться к вам, вы можете использовать различные варианты реализации (с хешем и без него) и посмотреть, стоит ли это реализовать или нет.
Основная задача в этой задаче - математическая по своей природе. Ваша цель состоит в том, чтобы обрезать пространство поиска, найдя интервалы значений для таких значений, как $ a, $ c, а затем вычисляющие ограничивающие интервалы для зависимых переменных, таких как $ c. – vladr