Вам нужно проанализировать рекламные объявления, чтобы получить тип аудиообъекта, индекс частоты и количество каналов. Затем напишите аудио конкретный конфиг. https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Audio_Specific_Config
Основная проблема в этой проблеме оптимизации является математической по своей природе.
Ваша цель, поскольку я могу вывести из Вашего определения 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 можно использовать Математику:: 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
... и скорректируйте ограничения так, чтобы только =
, <=
и >=
(в) равенствах используются (принятие дискретных т.е. целочисленных значений для наших переменных):
... то есть,
$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
, 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)
кортежи были уже протестированы, чтобы не тестировать их снова, если и только если:
Я использую Данные:: Ограничение. Вы пишете небольшие подпрограммы, которые реализуют отдельные ограничения, затем последовательно применяют все ограничения, которые Вы хотите. Я говорю об этом немного в Освоении Perl в "Динамических Подпрограммах" глава.
use Data::Constraint; Data::Constraint->add_constraint( 'a_less_than_b', run => sub { $_[1] < $_[2] }, description => "a < b", ); Data::Constraint->add_constraint( 'b_greater_than_c', run => sub { $_[2] > $_[3] }, description => "b > c", ); Data::Constraint->add_constraint( 'a_greater_than_0', run => sub { $_[1] > 0 }, description => "a > 0", ); Data::Constraint->add_constraint( 'c_less_than_30', run => sub { $_[3] < 30 }, description => "c < 30", ); Data::Constraint->add_constraint( 'a_is_odd_between_10_18', run => sub { return 1 if( $_[1] < 10 or $_[1] > 18); return 0 unless $_[1] % 2, }, description => "a is odd between 10 and 18", ); for ( 1 .. 10 ) { my( $a, $b, $c ) = gen_abc(); print "a = $a | b = $b | c = $c\n"; foreach my $name ( Data::Constraint->get_all_names ) { print "\tFailed $name\n" unless Data::Constraint->get_by_name( $name )->check( $a, $b, $c ), } } sub gen_abc { my $c = int rand 30; my $b = int rand $c; my $a = int rand $b; return ($a, $b, $c); }
Выполнение его, этот путь означает, что легко осмотреть результат для наблюдения то, что перестало работать вместо полного отказа:
a = 2 | b = 4 | c = 5 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 0 | c = 2 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 0 | c = 2 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 7 | b = 14 | c = 25 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 0 | c = 29 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 0 | c = 20 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 4 | c = 22 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 4 | b = 16 | c = 28 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 22 | c = 26 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c a = 0 | b = 3 | c = 6 Failed a_greater_than_0 Failed a_less_than_b Failed b_greater_than_c
Если Вы хотите что-то больше хардкора, мой Кирпичный модуль обрабатывает деревья ограничений, включая сокращение и ветвление. Эти вещи имеют смысл для больших систем, где Вы будете смешивать и соответствовать различным ограничениям для различных ситуаций, так как большая часть кода настраивает ограничительные объекты. Если у Вас только есть своя одна ситуация, Вы, вероятно, просто хотите придерживаться с тем, что Вы имеете.
Удача, :)
Я не уверен, что Вы собираетесь найти простой ответ на это (хотя я хотел бы быть доказанным неправым!).
Кажется, что Ваша проблема хорошо подошла бы для генетического алгоритма. Функцию фитнеса должно быть легко записать, просто выиграть 1 за каждое удовлетворенное ограничение, 0 иначе. AI:: Генетический, кажется, модуль, который мог помочь Вам, и написать код и понять то, что необходимо записать.
Это должно быть быстрее, чем метод грубой силы.
Я вместо этого создал бы алгоритм, который генерирует набор действительных списков, случайным образом сгенерированных или не (это должно быть тривиально), запишите им в файл и затем используйте тот файл для питания тестовой программы, таким образом, он может случайным образом выбрать любой список, он хочет.
"Реальный" ответ потребовал бы парсинга выражений и обоснования об отношениях. За исключением этого, я предложил бы использовать систематический обход пространства значений, вместо того, чтобы просто пробовать значения наугад. Например,
my $count = 0;
for (my $c = 0; $c < 30 && $count < $SOMELIMIT; ++$c) {
# check all other constraints on only $c here
# next if any fail
for (my $b = $c + 1; $b < $UPPERLIMIT && $count < $SOMELIMIT; ++$b) {
# check all other constraints on only $b and $c here
# next if any fail
for (my $a = 1; $a < $b && $count < $SOMELIMIT; ++$a) {
#check all remaining constraints on $a, $b, and $c here
# next if any fail
# now use surviving combinations
++$count;
}
}
}
Я поместил переменную с большинством отдельных ограничений на наиболее удаленном уровне, затем самом ограниченном следующий, и т.д.
По крайней мере, с этой структурой Вы не протестируете ту же комбинацию многократно (как случайная версия, очень вероятно, сделает), и если Вы наблюдаете, что она работает, можно видеть, что шаблоны появляются, который позволяет Вам прервать выполнение.