Как сгенерировать набор значений для набора булевых переменных в Ocaml - PullRequest
0 голосов
/ 13 января 2019

Допустим, у нас есть функция, которая принимает в качестве входных данных набор логических переменных: bol1, bol2 ... boln. Как мы можем перебрать все возможные логические назначения, используя минимальные коды? Мне нужно реализовать функцию, которая принимает на вход набор из двух логических переменных вместе с логическим выражением, включающим переменные, и создает таблицу истинности. Если вы посмотрите на мой код, это долго. ТАК, я хочу уменьшить это. Кроме того, способ, которым я это сделал, кажется избыточным, так как компилятор выдает предупреждение о том, что регистр совпадений | Var v2 не используется для всех регистров совпадений | Var v2 в коде.

Это упражнения 46/47 в this link : "Определить функцию table2, которая возвращает таблицу истинности данного логического выражения в двух переменных (указанных в качестве аргументов). Возвращаемое значение должно быть список троек, содержащих (value_of_a, balue_of_b, value_of_expr). "

type bool_expr =
  | Var of string
  | Not of bool_expr
  | And of bool_expr * bool_expr
  | Or of bool_expr * bool_expr 

let table2 (v1 : string) (v2 : string ) (exp : bool_expr)= 
  let rec evaluate (bol1 : bool) (bol2 : bool) (expp : bool_expr) =
    match bol1, bol2 with
    |true, true -> (match expp with
        |Var v1 -> true
        |Var v2 -> true
        |Not q -> not (evaluate bol1 bol2 q )
        |And (q,w) -> (evaluate bol1 bol2 q) && (evaluate bol1 bol2 w)
        |Or (q, w) -> (evaluate bol1 bol2 q) || (evaluate bol1 bol2 w))
    |true, false -> (match expp with
        |Var v1 -> true
        |Var v2 -> false
        |Not q -> not (evaluate bol1 bol2 q )
        |And (q,w) -> (evaluate bol1 bol2 q) && (evaluate bol1 bol2 w)
        |Or (q, w) -> (evaluate bol1 bol2 q) || (evaluate bol1 bol2 w))
    |false, true -> (match expp with
        |Var v1 -> false
        |Var v2 -> true
        |Not q -> not (evaluate bol1 bol2 q )
        |And (q,w) -> (evaluate bol1 bol2 q) && (evaluate bol1 bol2 w)
        |Or (q, w) -> (evaluate bol1 bol2 q) || (evaluate bol1 bol2 w))
    |false, false -> (match expp with
        |Var v1 -> false
        |Var v2 -> false
        |Not q -> not (evaluate bol1 bol2 q )
        |And (q,w) -> (evaluate bol1 bol2 q) && (evaluate bol1 bol2 w)
        |Or (q, w) -> (evaluate bol1 bol2 q) || (evaluate bol1 bol2 w))
  in [(true,true, (evaluate true true exp));(true,false, (evaluate true false exp));(false,true, (evaluate false true exp));(false,false, (evaluate false false exp))]

Вот пример ожидаемого результата:

table2 "a" "b" (And (Var "a", Or (Var "a", Var "b"))) ;;

  • : (bool * bool * bool) list = [(правда, правда, правда); (правда, ложь, правда); (ложь, правда, ложь); (ложь, ложь, ложь)]

Ответы [ 2 ]

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

Вы можете сократить свой код в 4 раза, если вы не соответствуете bol1 и bol2, а просто используете их.

(match expp with
   | Var v1 -> bol1
   | Var v2 -> bol2
   ...

Во-вторых, сопоставление сравнивает не переменные, а структуру. Сопоставление с Var v1 связывает значение expp с новой переменной v1. Два случая Var v1 и Var v2 имеют одинаковую структуру, а второй случай никогда не достигается.

Для сравнения значений необходимо написать:

| Var v when v == v1 -> bol1
| Var v when v == v2 -> bol2
| Var v -> (* neigther v1 nor v2, what to do now? *)

Что касается расширения этого на таблицы с большим количеством столбцов, вам придется использовать рекурсию и списки или массивы вместо кортежей. Например. type table = ((bool list) * bool) list

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

Подсказка: попробуйте посмотреть на проблему рекурсивно.

bool_values { b_0, b_1, .... b_n } =
  { T + bool_values { b_1. ... b_n } } +
  { F + bool_values { b_1. ... b_n } }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...