Як перетворити таблицю істинності в найменший можливий блок if / else


20

Як я можу взяти таблицю правдивості і перетворити її в ущільнену, якщо блок?

Наприклад, скажімо, у мене є ця таблиця істинності, де 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.


10
ти маєш на увазі перетворення карти Карно в каскад ifelse?
храповик урод

@ratchet: Здається, я це роблю? Я про них раніше не знав. Доведеться зробити читання, але все-таки і додаток, який би зробив це для мене, було б добре, якщо нічого іншого, щоб перевірити свої результати, зроблені вручну.
Хуан

1
@jalayn більшість інструментів карно для цифрових схем; вони мають іншу евристику, ніж те, про що йдеться
щурячий вирод

1
@jsoldi: відповіді, які ви отримаєте, залежатимуть від того, який веб-сайт ви запитуєте. Якщо ви шукаєте коментарі до певного фрагмента коду, що містить кілька блоків if-then-else, він, безумовно, належить до перегляду коду (бета) . Stackoverflow навчить вас інструментів та прийомів. На programmers.SE люди скажуть вам, чи слід / не варто піклуватися про перезапис логічних висловлювань для розуміння людьми чи для швидшого виконання.
rwong

2
Рекомендації інструментальні по темі, але якщо ви зміните питання в «Як я це зробити?» це буде на тему. Якщо ви хочете отримати рекомендації щодо програмного забезпечення, слід перейти на softwarerecs.stackexchange.com.
Кіліан Фот

Відповіді:


14

Якщо ви розробляєте з карти Карно, код також може виглядати так:

//                   a      b
def actionMap = [ false: [false: { z() },
                          true:  { z() }],
                  true:  [false: { x() },
                          true:  { y() }]]

actionMap[a][b]()

Яка мова це? Javascript? Пітон?
TheLQ

TheLQ, його не python, може бути javascript. Але було б дуже схоже, якби це було написано python
grizwako

@TheLQ: це Groovy, тому що саме цим я займаюсь сьогодні, і, мабуть, і Рубі. Код Javascript або Python, LUA або Perl був би дуже схожим.
Кевін Клайн

2
Це, звичайно, має наслідком оцінювання b навіть тоді, коли оцінка не потрібна. Можливо, це проблема, можливо, це не так.
Псевдонім

@kevincline будь ласка, досить будь ласка, "Lua", а не "LUA". :)
Мачадо

4

У C # .NET ви можете скористатися класом словника, щоб отримати результат без будь-якого IF ELSE, як описано нижче.

  1. Він читабельний
  2. Нові клавіші будуть унікальними (інакше ви отримаєте помилку)
  3. Послідовність значення не має
  4. Легко додавати або видаляти записи

Якщо у вас немає еквівалента класу словників, ви можете зробити те ж саме у двійковій функції пошуку / пошуку.

//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();

1
Мені подобається це рішення, єдиною зміною, яку я вніс би, було б використання словника <Tuple <bool, bool>, Tuple <bool, bool, bool> замість словника <string, string>. Тоді вам не потрібно будувати рядок для пошуку та деконструкції результату після цього, оскільки Tuples зробить це за вас.
Ліза

@Lyise, Дякую за ваше зауваження. Ви абсолютно правильні. Я повинен включити вашу добру думку, коли отримаю шанс.
NoChance

2

Що ви хочете, це алгоритм Рете . Це автоматично комбінує набір правил і надає їм пріоритет на дерево, як ви описуєте.

Існує ряд комерційних систем "двигуна правил", які роблять це в дуже великих масштабах (мільйони правил), коли швидкість виконання є важливою.


2

Ось ваша бібліотека :) І вам не потрібно передавати повну K-таблицю, лише поля, які вас цікавлять :) Це передбачає, що її І оператор в таблиці правдивості. Якщо ви хочете використовувати більше операторів, ви повинні мати можливість їх переписати. Ви можете мати будь-яку кількість аргументів. Написано 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()

1

Зіставте введення в одне значення, а потім увімкніть його:

#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

1

Таблиця пошуку, що містить покажчики функцій, може добре працювати в деяких ситуаціях. Наприклад, в 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 починає некрасиво. Якщо у вас так багато матеріалів, спершу спробуйте спростити їх іншими способами (наприклад, картами Карно).


0

Подивіться на програмне забезпечення "Чудовий Карно" - воно може сприймати таблиці істинності досить точно як ваш зразок, приймати визначення аналітичних булевих формул, приймати сценарії Lua для створення таблиць істинності. Далі програмне забезпечення "Чудовий Карно" малює K-Maps для прийнятого введення, яке ви можете мінімізувати вручну або за допомогою логічного мінімізатора "Еспресо", а також виробляє вихід для C / C ++ та деяких апаратних мов. Перегляньте сторінку підсумкових функцій для "Чудовий Карнау" - http://purefractalsolutions.com/show.php?a=xgk/gkm


Це виглядає дуже як те, що мені потрібно, але не зміг отримати код C / C ++, щоб показати щось, крім порожнього ifs після введення таблиці істинності.
Хуан

Так, цей інструмент, призначений для мінімізації логічних функцій - після введення таблиці істинності вам потрібно мінімізувати логічну функцію (PoS / SoP - на 0 / на 1). Код C ++ можна знайти у вікні «Результати мінімізації» після мінімізації.
Петрукіо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.