Problema A - Representação de funções booleanas sob a forma de fórmulas de lógica proposicional FND/FNC
DI-UBI | Lógica Computacional | 2021/2022
Uma função booleana é uma função cujos argumentos e resultado são valores
pertencentes a um conjunto de dois elementos (representados geralmente por
Qualquer função booleana com
Dadas duas fórmulas de lógica proposicional,
Uma função booleana pode também ser representada sob a forma de uma tabela de verdade que lista explicitamente o seu valor para todos os valores possíveis dos seus argumentos.
0 | 0 | 0 | 1 |
0 | 0 | 1 | 0 |
0 | 1 | 0 | 0 |
0 | 1 | 1 | 1 |
1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 |
1 | 1 | 0 | 1 |
1 | 1 | 1 | 1 |
Tabela 1: Tabela de verdade para uma função booleana
Problema
O objetivo deste problema é, dada uma função booleana sob a forma de uma tabela de verdade que a representa, obter duas proposições da lógica proposicional equivalentes a essa função, uma em Forma Normal Conjuntiva (FNC) e outra em Forma Normal Disjuntiva.
Forma Normal Conjuntiva
Uma fórmula diz-se em forma normal conjuntiva se for da forma:
onde cada
Cada conjunto de disjunções (disjuntório
Forma Normal Disjuntiva
Uma fórmula diz-se em forma normal disjuntiva se for da forma:
onde cada
Cada conjunto de conjunções (
Input
Primeira linha: valor
Input exemplo
3
0 0 0 1
0 0 1 0
0 1 0 0
0 1 1 1
1 0 0 0
1 0 1 0
1 1 0 1
1 1 1 1
(Corresponde à função booleana representada na Tabela 1.)
Output
Primeira linha: string com a fórmula equivalente à função booleana
Segunda linha: string com a fórmula equivalente à função booleana
Para formar as fórmulas, deverá associar a cada variável
Deverá ser usado tipo formula
e a função print_formula
(incluídas abaixo) para construir e imprimir as fórmulas geradas, sob pena de a solução ser rejeitada pelo Mooshak caso use outro método.
Output exemplo
((!a & b & c) | (!a & !b & !c) | (a & b & c) | (a & b & !c))
((a | b | !c) & (a | !b | c) & (!a | b | c) & (!a | b | !c))
Sugestão de resolução
É possível obter uma fórmula de lógica proposicional na forma FND equivalente a uma
função booleana
Tomemos o exemplo da Tabela 1. Às variáveis
O disjuntório de todos os conjuntórios obtidos da tabela de verdade da função
booleana
Portanto, por observação da Tabela 1, podemos obter a seguinte fórmula FND que é
equivalente à função booleana
É possível obter uma fórmula FNC equivalente a uma função booleana
Deste modo, da Tabela 1 obtemos a seguinte fórmula FND equivalente a
e a sua negação
é uma fórmula FNC equivalente a
Template da solução a submeter
Deverá utilizar o template abaixo para escrever a solução deste problema.
(* Cabeçalho a incluir *)
type formula =
| Lit of char
| Neg of char
| Conj of formula * formula
| Disj of formula * formula
let rec compare_formula f_1 f_2 =
match (f_2, f_1) with
| Lit c_1, Lit c_2 | Neg c_1, Neg c_2 -> Char.compare c_1 c_2
| Lit c_1, Neg c_2 when c_1 = c_2 -> -1
| Neg c_1, Lit c_2 when c_1 = c_2 -> 1
| (Lit c_1 | Neg c_1), (Lit c_2 | Neg c_2) -> Char.compare c_1 c_2
| (Lit _ | Neg _), (Disj _ | Conj _) -> -1
| (Disj _ | Conj _), (Lit _ | Neg _) -> 1
| Conj (f_1_1, f_1_2), Conj (f_2_1, f_2_2)
| Disj (f_1_1, f_1_2), Disj (f_2_1, f_2_2) ->
let c = compare_formula f_1_1 f_2_1 in
if c = 0 then compare_formula f_1_2 f_2_2 else c
| Conj _, Disj _ | Disj _, Conj _ -> 0
let rec normalize_conjs acc f_1 f_2 =
match (f_1, f_2) with
| Conj (f_1_1, f_1_2), Conj (f_2_1, f_2_2) ->
normalize_conjs (normalize_conjs acc f_1_1 f_1_2) f_2_1 f_2_2
| (Lit _ | Neg _ | Disj _), Conj (f_1', f_2') ->
normalize_conjs (normalize_formula f_1 :: acc) f_1' f_2'
| Conj (f_1', f_2'), (Lit _ | Neg _ | Disj _) ->
normalize_formula f_2 :: normalize_conjs acc f_1' f_2'
| _ -> normalize_formula f_2 :: normalize_formula f_1 :: acc
and normalize_disjs acc f_1 f_2 =
match (f_1, f_2) with
| Disj (f_1_1, f_1_2), Disj (f_2_1, f_2_2) ->
normalize_disjs (normalize_disjs acc f_1_1 f_1_2) f_2_1 f_2_2
| (Lit _ | Neg _ | Conj _), Disj (f_1', f_2') ->
normalize_disjs (normalize_formula f_1 :: acc) f_1' f_2'
| Disj (f_1', f_2'), (Lit _ | Neg _ | Conj _) ->
normalize_formula f_2 :: normalize_disjs acc f_1' f_2'
| _ -> normalize_formula f_2 :: normalize_formula f_1 :: acc
and normalize_formula = function
| (Lit _ | Neg _) as f -> f
| Conj (f_1, f_2) -> (
match normalize_conjs [] f_1 f_2 |> List.sort compare_formula with
| x :: xs -> List.fold_left (fun f acc -> Conj (acc, f)) x xs
| _ -> assert false)
| Disj (f_1, f_2) -> (
match normalize_disjs [] f_1 f_2 |> List.sort compare_formula with
| x :: xs -> List.fold_left (fun f acc -> Disj (acc, f)) x xs
| _ -> assert false)
exception Malformed
let normalize_disjs f =
let rec aux acc = function
| (Lit _ | Neg _ | Conj _) as f -> f :: acc
| Disj (((Lit _ | Neg _ | Conj _) as f_1), f_2) -> aux (f_1 :: acc) f_2
| Disj (Disj _, _) -> raise Malformed
in
aux [] f |> List.rev
let normalize_conjs f =
let rec aux acc = function
| (Lit _ | Neg _ | Disj _) as f -> f :: acc
| Conj (((Lit _ | Neg _ | Disj _) as f_1), f_2) -> aux (f_1 :: acc) f_2
| Conj (Conj _, _) -> raise Malformed
in
aux [] f |> List.rev
let string_of_formula =
let rec aux conj disj f = function
| Lit c -> f (Char.escaped c)
| Neg c -> f ("!" ^ Char.escaped c)
| Conj (f_1, f_2) ->
aux true false
(fun s_1 ->
aux true false
(fun s_2 ->
f
(if conj then s_1 ^ " & " ^ s_2
else "(" ^ s_1 ^ " & " ^ s_2 ^ ")"))
f_2)
f_1
| Disj (f_1, f_2) ->
aux false true
(fun s_1 ->
aux false true
(fun s_2 ->
f
(if disj then s_1 ^ " | " ^ s_2
else "(" ^ s_1 ^ " | " ^ s_2 ^ ")"))
f_2)
f_1
in
aux false false (fun x -> x)
let print_formula f = normalize_formula f |> string_of_formula |> print_endline
(* Escreva a solução do problema a seguir *)