真理値表を取得して、圧縮されたifブロックに変換するにはどうすればよいですか?
たとえば、AとBが条件であり、x、y、zが可能なアクションである次の真理値表があるとします。
A B | x y z
-------------
0 0 | 0 0 1
0 1 | 0 0 1
1 0 | 0 1 0
1 1 | 1 0 0
これは以下のブロックに変換できます:
if(A)
{
if(B)
{
do(x)
}
else
{
do(y)
}
}
else
{
do(z)
}
これは簡単なサンプルですが、さまざまな方法で組み合わせるとさまざまな出力が生成されるいくつかの条件が頻繁にあり、ifブロックでロジックを表す最もコンパクトでエレガントな方法を理解するのが難しくなります。
Karnaughマップから設計している場合、コードもそのように見える場合があります。
// a b
def actionMap = [ false: [false: { z() },
true: { z() }],
true: [false: { x() },
true: { y() }]]
actionMap[a][b]()
C#.NETでは、次のように、辞書クラスを使用してIF ELSEなしで結果を取得できます。これの良い点は次のとおりです。
辞書クラスに相当するものがない場合は、バイナリルックアップ/検索関数で同じことができます。
//A B | x y z
//-------------
//0 0 | 0 0 1
//0 1 | 0 0 1
//1 0 | 0 1 0
//1 1 | 1 0 0
// Create a Dictionary object and populate it
Dictionary<string, string> _decisionTable = new Dictionary<string, string>() {
{ "0,0", "0,0,1" },
{ "0,1", "0,0,1" },
{ "1,0", "0,1,0" },
{ "1,1", "1,0,0"}
};
//usage example: Find the values of X,Y,Z for A=1,B=0
Console.WriteLine(_decisionTable["1,0"]);
Console.Read();
欲しいのは Reteアルゴリズム です。これにより、一連のルールが自動的に結合され、記述したとおりにツリーに優先順位が付けられます。
実行速度が重要な非常に大規模な(何百万ものルール)でこれを実行する多くの商用「ルールエンジン」システムがあります。
ここにあなたのライブラリがあります:)そして、あなたが興味のあるフィールドだけを完全なKテーブルを渡す必要はありません:)それは真理値表のAND演算子を想定しています。より多くの演算子を使用したい場合は、それを書き換えることができるはずです。引数はいくつでも持つことができます。 python
で記述され、テストされています。
def x():
print "xxxx"
def y():
print "yyyyy"
def z(): #this is default function
print "zzzzz"
def A():
return 3 == 1
def B():
return 2 == 2
def insert(statements,function):
rows.append({ "statements":statements, "function":function })
def execute():
for row in rows:
print "==============="
flag = 1
for index, val in enumerate(row["statements"]):
#for first pass of lopp, index is 0, for second its 1....
#if any function returns result different than one in our row,
# we wont execute funtion of that row (mark row as not executable)
if funcs[index]() != val:
flag = 0
if flag == 1:
#we execute function
row["function"]()
else: z() #we call default function
funcs = [A,B] #so we can access functions by index key
rows = []
insert( (0,0), y)
insert( (0,1), y)
insert( (1,0), x)
insert( (1,1), x)
insert( (0,1), x)
execute()
入力を単一の値にマップし、次にそれをオンにします。
#define X(a, b) (!!(a) * 2 + !!(b))
switch(X(A, B)) {
case X(0, 0):
...
break;
case X(0, 1):
...
break;
case X(1, 0):
...
break;
case X(1, 1):
...
break;
}
#undef X
関数ポインタを含むルックアップテーブルは、状況によってはうまく機能します。たとえばCでは、次のようなことができます。
typedef void(*VoidFunc)(void);
void do(int a, int b)
{
static VoidFunc myFunctions[4] = {z, z, y, x}; // the lookup table
VoidFunc theFunction = myFunctions[ a * 2 + b ];
theFunction();
}
テーブルのエントリ数は2 ^^ nである必要があるため、これは入力数が比較的少ない場合に適切なソリューションです。ここで、nは入力数です。 7つまたは8つの入力は扱いやすく、10または12は醜くなり始めます。入力がそれだけ多い場合は、最初に他の方法(カルノーマップなど)で単純化してみてください。
「Gorgeous Karnaugh」ソフトウェアを見てください。サンプルとまったく同じ真理値表を受け入れ、分析ブール式の定義を受け入れ、Luaスクリプトを受け入れて真理値表を作成できます。次に、「Gorgeous Karnaugh」ソフトウェアは、手動で、または「Espresso」ロジックミニマイザーを使用して最小化できる入力された入力に対してK-Mapを描画し、C/C++および一部のハードウェア言語の出力を生成します。 「Gorgeous Karnaugh」の概要機能ページをご覧ください- http://purefractalsolutions.com/show.php?a=xgk/gkm