方法を解決するための制約Perl?
-
05-09-2019 - |
質問
私は、以下の設定の制約を含んだサンプル設定の制約なくなるのではないだろうかする必要があり):
$a < $b
$b > $c
$a is odd => $a in [10..18]
$a > 0
$c < 30
いるのに必要一覧 ($a, $b, $c)
に応える。私の素朴液
sub check_constraint {
my ($a, $b, $c) = @_;
if !($a < $b) {return 0;}
if !($b > $c) {return 0;}
if (($a % 2) && !(10 <= $a && $a <= 18)) {return 0;}
if !($a > 0) {return 0;}
if !($c < 30) {return 0;}
return 1;
}
sub gen_abc {
my $c = int rand 30;
my $b = int rand $c;
my $a = int rand $b;
return ($a, $b, $c);
}
($a, $b, $c) = &gen_abc();
while (!&check_constraint($a, $b, $c)) {
($a, $b, $c) = &gen_abc();
}
現在、このソリューションな保証終了するには、やは非効率です。あると良いこのPerl?
編集: このためにランダム試験発電機、溶液を利用する必要がランダムなどの機能を rand()
.液が完全に決定的なものの場合はそのソリューションができないリストで組み合わせでの選択インデックスのランダム:
@solutions = &find_allowed_combinations(); # solutions is an array of array references
$index = int rand($#solutions);
($a, $b, $c) = @$solution[$index];
編集2: の制約は簡単に解決する力.しかし、多い場合には、変数の大規模な範囲の可能な値力なオプションになります。
解決
本課題ではこの最適化問題の数理です。
ことが明らの定義 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); # 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
したい場合はのようにハードコア、 レンガ モジュールを取り扱う木々の制約を含め、枝打ちやす。これらのこえる大きなシステムでは、種々の制約のための異なる状況で、ほとんどのコードは設定の制約オブジェクト。いただけるお客様にはご一の状況だというこだわかっています。
良:)
"真"の回答が必要と解析の表現と推論いです。短い、どうしたらいいでしょうかい提案を体系的にフォーカストラバーサルの値をスペースだけでなく、い値かせとなります。例えば、
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;
}
}
}
私は、変数の個々の制約の一番外側のレベル、最も制約のある、など。
少なくともこのように構成んテストは、組み合わせを複数回のランダム版のものになる可能性が高いと思われる)まで行って見える場合がありパターンがまとめて見ることができるカットを実行す。
この シモ::制 はん
私が代わりに作成アルゴリズムを生成するバンチの有効なリスト、ランダムに生成されるためになっているものと考えられる)を書くファイルとして使用するファイルを飼料の試験プログラムで彼はランダムにピリストでついてお聞きしましょう。