Оптимальная реализация таблицы истинности - PullRequest
0 голосов
/ 08 января 2019

Я определил таблицу истинности, такую ​​как приведенная ниже

prev_state| input1         | input2 |next_state| Action
(def/new) |(Disable/Enable)|(Off/On)|          |
def       | D              | Off    | def      | Nothing
def       | D              | On     | def      | Nothing
def       | E              | Off    | def      | Nothing
def       | E              | On     | new      | call function1
new       | D              | Off    | def      | call function2
new       | D              | On     | def      | call function2
new       | E              | Off    | def      | call function2
new       | E              | On     | new      | Nothing

Мне было интересно, какое минимальное количество проверок вам нужно для достижения этой цели.

Думаю ли я использовать карту Карно , такую ​​как следующая:

    00| 01| 11| 10 
  -----------------
0 | A | A | B | A |  
  -----------------
1 | C | C | A | C |  
  -----------------

Где A ничего не соответствует, B вызывать function1 и C вызывать function2

В соответствии с тем, что я вижу, у вас есть 2 комбинации по 2 А и по одной Всего 3 для А 1 для B и 2 комбинации из 2 C

Значит ли это, что минимальное количество сравнений составляет 3 + 1 + 2 = 6? Но поскольку А ничего не делают, минимальная реализация потребует только 3 комбинации для B и C?

Выполнение теста

if (prev_state == new && input1 == disable) {
    function2();
}
else if (prev_state == new && input2 == Off) {
    function2();
}
else if (input1 == enable && input2 == On) {
    function1();
}

Также теперь, когда я вижу, что лучше, чем выше или этот:

if ((prev_state == new && input1 == disable) || (prev_state == new && input2 == Off)) {
    function2();
}
else if (input1 == enable && input2 == On) {
    function1();
}

Спасибо за тех, кто предложил справочную таблицу с O (1), но занимающую место в памяти. Теперь я понимаю, что предпочел бы иметь решение, не использующее дополнительную память. Согласны ли вы с тем, что использование карт Карно является допустимым методом для получения минимального количества сравнений?

Ответы [ 4 ]

0 голосов
/ 08 января 2019

Я бы сделал что-то вроде ниже.

int check = (int)((prev_state == new) << 2 | (input1 == E)<<1 | (input2 == on));

/*def       | E              | On     | new      | call function1 == 3
  new       | D              | Off    | def      | call function2 == 4
  new       | D              | On     | def      | call function2 == 5
  new       | E              | Off    | def      | call function2 == 6 */

if (check == 4 || check == 5 || check == 6)
  function2();
else if (check == 3)
  function1();
0 голосов
/ 08 января 2019

Мне было интересно, каково минимальное количество проверок, которое нужно выполнить ...

ноль. Используйте справочную таблицу

void f_Nothing(void) {
  ; // do nothing
}

void f_function1(void) {
  ;  // something interesting
}

void f_function2(void) {
  ;  // something interesting
}

int main(void) {

  typedef void (*fun_type)(void);

  fun_type f[2][2][2] = { //
      {{f_Nothing, f_Nothing}, {f_Nothing, f_function1}}, 
      {{f_function2, f_function2}, {f_function2, f_Nothing}}};
  bool prev_state, input1, input2;
  //...
  f[prev_state][input1][input2]();

ОП позже прокомментировал в поисках решения, которое ... не использует дополнительную память .

if ( (input1 == E && input2 == ON) && (prev_state == def)) function1();
if (!(input1 == E && input2 == ON) && (prev_state == new)) function2();

// or

if (input1 == E && input2 == ON) {
  if (prev_state == def) function1();
} else {
  if (prev_state == new) function2();
}
0 голосов
/ 08 января 2019

Вы можете удалить несколько повторных тестов, но имеет ли это большое значение на практике, зависит от оптимизации компилятора.

if (prev_state == new) {
    if (input1 == disable || input2 == Off) {
        function2();
    }
} else {
    if (input1 == enable && input2 == On) {
        function1();
    }
}

Или:

if (input1 == disable || input2 == Off) {
    if (prev_state == new) {
        function2();
    }
} else {
    if (prev_state == def) {
        function1();
    }
}
0 голосов
/ 08 января 2019

Если поведение статичное, делать тесты бесполезно, вы можете

  • использовать трехмерный массив, где каждое значение является парой следующего состояния и действия, первое измерение - prev_state 0/1, второй вход 1 D / E -> 0/1, третий вход2 выключен / включен -> 0/1

  • но поскольку ваши входные данные очень ограничены, вы также можете закодировать 3 индекса только в один = prev_state * 4 + input1 * 2 + input2 и использовать простой вектор размера 8. Как Шверн предлагает в замечании, вы также можете сделать переключатель / случай по результату prev_state * 4 + input1 * 2 + input2

...