Come trasformare la tavola della verità nel più piccolo possibile se / else blocco

20

Come posso prendere una tabella di verità e trasformarla in un blocco compatto se?

Per esempio, diciamo che ho questa tabella di verità dove A e B sono condizioni e x, y e z sono azioni possibili:

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

Questo potrebbe trasformarsi in sotto se il blocco:

if(A)
{
    if(B)
    {
        do(x)
    }
    else
    {
        do(y)
    }
}
else
{
    do(z)
}

Questo è un esempio semplice, ma spesso ho diverse condizioni che combinate in modi diversi dovrebbero produrre output diversi e diventa difficile capire il modo più compatto ed elegante per rappresentare la loro logica in un blocco if.

    
posta Juan 22.08.2011 - 07:13
fonte

7 risposte

14

Se stai progettando da una mappa di Karnaugh, allora anche il codice potrebbe sembrare così:

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

actionMap[a][b]()
    
risposta data 22.08.2011 - 16:30
fonte
4

In C # .NET, puoi usare una classe Dizionario per ottenere il risultato senza IF SEI come segue: La cosa bella di questo è:

  1. È leggibile
  2. Le nuove chiavi saranno univoche (altrimenti si ottiene un errore)
  3. La sequenza non ha importanza
  4. Facile aggiungere o rimuovere voci

Se non hai un equivalente di Dizionario, puoi fare lo stesso in una funzione di ricerca / ricerca binaria.

//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();
    
risposta data 22.08.2011 - 22:40
fonte
2

Quello che vuoi è un algoritmo Rete . Questo sistema automaticamente un set di regole e le assegna come priorità in un albero nel modo in cui descrivi.

Esistono numerosi sistemi di "regole del motore" commerciali che lo fanno su larga scala (milioni di regole) in cui la velocità di esecuzione è essenziale.

    
risposta data 22.08.2011 - 23:07
fonte
2

Ecco la tua libreria :) E non hai bisogno di passare la tabella K completa, solo i campi che ti interessano :) Presume che il suo operatore AND nella tabella di verità. Se vuoi utilizzare più operatori, dovresti essere in grado di riscriverlo. Puoi avere un numero qualsiasi di argomenti. Scritto in python e testato.

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()
    
risposta data 22.08.2011 - 07:47
fonte
1

Mappare gli input in un singolo valore e quindi accenderlo:

#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
    
risposta data 18.08.2017 - 22:06
fonte
1

Una tabella di ricerca contenente i puntatori di funzioni può funzionare bene in alcune situazioni. In C, ad esempio, puoi fare qualcosa di simile:

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

Questa è una buona soluzione quando il numero di input è relativamente piccolo, poiché il numero di voci nella tabella deve essere 2 ^^ n dove n è il numero di input. 7 o 8 ingressi potrebbero essere gestibili, 10 o 12 inizia a diventare brutti. Se hai molti input, prova a semplificare con altri mezzi (come le mappe di Karnaugh).

    
risposta data 02.01.2012 - 06:41
fonte
0

Guarda il software "Gorgeous Karnaugh" - può accettare tabelle di verità del tutto esatte come campione, accettare la definizione analitica delle formule booleane, accettare lo scripting Lua per costruire tabelle di verità. Successivamente, il software "Gorgeous Karnaugh" disegna le K-Maps per gli input presi, che è possibile ridurre a icona manualmente o utilizzando il minimizzatore logico "Espresso" e produce output per C / C ++ e alcuni linguaggi hardware. Vai alla pagina delle caratteristiche di riepilogo per "Gorgeous Karnaugh" - link

    
risposta data 02.01.2012 - 05:59
fonte