Contents

计算真值表

程序设计说明

本来想用 lisp 程序来写,他的写法是

(function arg1 arg2 ...)

S表达式不需要考虑优先级顺序,写起来比较简单 但是在这里有太多运算符,写成 lisp 很不方便

p∧¬(q→p
(p ↔ q) → r
p → (p ∨ ¬q ∨ r)

还好有 Julia ,他可以自定义运算符 首先将运算符作为一个函数定义(以下例子这样写是因为 + 在程序中是特殊符号,需要加一个 : 前缀来标识, Julia 语言的一个 feature)

function Base.:+(arg1::SomeType, arg2::SomeType)
  return arg1 * arg2
end

解释器就可以把以下语句

arg1 + arg2

解析为

Base:+(arg1, arg2)

如果是调用多次

arg1 + arg2 + arg3

可以看作先对前两个进行求值,得出结果,与第三个参数求值

实现细节

演示说明

这里给出一个演示的例子

print(TruthTable("(p ↔ q) → r", [:p, :q, :r], (p, q, r) -> (p  q)  r))

需要自定义真值表的

  1. 标题
  2. 参数表
  3. 生成真值的逻辑函数

运算符定义

¬(p::Bool) = !p # negative
(p::Bool, q::Bool) = p && q #conjunction, use \wedge
(p::Bool, q::Bool) = p || q #disjunction, use \vee
(p::Bool, q::Bool) = begin #implication, use \rightarrow
  !(p == true && q == false)
end

(p::Bool, q::Bool) = p == q #equivalence, use \leftrightarrow

这些函数我都是通过参考真值表写出来的,一开始看符号推演我都看懵了,他娘的什么玩样,要我死记硬背,还不如自己写一个

真值表结构

struct TruthTable
  caption::String
  params::Vector{Symbol}
  target::Function
end

我为真值表定义了三个 field

  1. __caption__ 标题
  2. __target__ 计算出真值的函数定义
  3. __params__ 为 target 配套的参数列表,每个都是符号类型

计算真值并打印

Julia 语言中可以重载 print 函数来打印 TruthTable 结构体,通过访问 TruthTable 结构体 就可以查看对应的真值表 这里需要用到第三方库 DataFrames

function Base.print(truthTable::TruthTable)
  table = DataFrames.DataFrame()
  len = length(truthTable.params)
  rows = 2 ^ len
  logicTable = reshape(collect(Iterators.product(repeat([[true, false]], len)...)), rows)

  for (symbol, index) in Iterators.zip(truthTable.params, Iterators.countfrom(1, 1))
    table[!, symbol] = map(nums -> nums[index], logicTable)
  end

  results = map(nums -> truthTable.target(nums...), logicTable)
  table[!, truthTable.caption] = results

  println(table)
end

效果展示