提问人:Alvaro Rivera 提问时间:7/28/2022 最后编辑:Alvaro Rivera 更新时间:8/1/2022 访问量:268
具有布尔函数的真值表
Truth table with Boolean Functions
问:
我正在尝试在 python 中使用 PANDAS 生成真值表。 我得到了一个布尔网络,有 3 个外部节点(U1、U2、U3)和 6 个内部节点(v1、v2、v3、v4、v5、v6)。 我创建了一个表,其中包含 3 个外部节点的所有可能组合,即 2^3 = 8。
import pandas as pd
import itertools
in_comb = list(itertools.product([0,1], repeat = 3))
df = pd.DataFrame(in_comb)
df.columns = ['U1','U2','U3']
df.index += 1
U1 | U2系列 | U3系列 |
---|---|---|
0 | 0 | 0 |
0 | 0 | 1 |
0 | 1 | 0 |
0 | 1 | 1 |
1 | 0 | 0 |
1 | 1 | 0 |
1 | 0 | 1 |
1 | 1 | 1 |
我还创建了相同的表,但具有 6 个内部节点的所有可能组合,即 2^6 = 64 个组合。
还给出了每个节点的函数
v1(t+1) = U1(t)
v2(t+1) = v1(t) and U2(t)
v3(t+1) = v2(t) and v5(t)
v5(t+1) = not U3(t)
v6(t+1) = v5(t) or v3(t)
真值表必须用 PANDAS 完成,它必须显示所有组合以及每个可能的组合。
例如。
v1 | v2 | v3 版本 | v4 版本 | v5 版本 | v6 版本 | 0 0 0 | 0 0 1 | 0 1 0 |
---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 000010 | 000000 | 000010 |
0 | 0 | 0 | 0 | 0 | 1 | |||
0 | 0 | 0 | 0 | 1 | 0 | |||
0 | 0 | 0 | 0 | 1 | 1 |
上表是最终产品应该如何的示例。其中 [0 0 0] 是外部节点的第一个组合。
我对如何计算每个基因的功能以及如何过滤数据并最终得到像这里这样的新表感到困惑。
在这里,我附上了我要解决的问题的图片:
答:
您似乎忽略了这样一个事实,即您的网络不仅有 3 个输入,因为“旧状态”也被视为输入 - 这就是反馈组合网络的作用,它将旧状态 + 输入转换为新状态(并且经常输出)。
这意味着您有 3+6 个输入,用于 2^9=512 个组合。打印时不太容易理解,但仍然可以。我修改了你的代码来打印这个(请注意,我对熊猫很陌生,所以这个代码肯定可以改进)
import pandas as pd
import pandas as pd
import itertools
#list of (u, v) pairs (3 and 6 elements)
# uses bools instead of ints
inputs = list((row[0:3],row[3:]) for row in itertools.product([False,True], repeat = 9))
def new_state(u, v):
# implement the itnernal nodes
return (
u[0],
v[0] and u[1],
v[1] and v[4],
v[2],
not u[2],
v[4] or v[2]
)
new_states = list(new_state(u, v) for u,v in inputs)
# unzip inputs to (u,v), add new_states
raw_rows = zip(*zip(*inputs), new_states)
def format_boolvec(v):
"""Format a tuple of bools like (False, False, True, False) into a string like "0010" """
return "".join('1' if b else '0' for b in v)
formatted_rows = list(map(lambda row: list(map(format_boolvec, row)), raw_rows))
df = pd.DataFrame(formatted_rows)
df.columns = ['U', "v(t)", "v(t+1)"]
df.index += 1
df
它的核心是接受输入和旧状态对并产生新状态的函数。这是您的规范的直接翻译。new_state
(u, v)
我修改了您的行以使用 s,生成 length-9 结果并将它们拆分为 3+6 长度的元组。为了仍然以您的格式打印,我添加了该功能。除此之外,它应该很容易理解,但如果您需要更多解释,可以自由发表评论。itertools.product
bool
format_boolvec(v)
要找到从给定开始状态到给定结束状态的输入序列,您可以自己手动完成,但这很乏味。我建议使用图形算法,它很容易实现,因为我们也知道所需路径的长度,所以我们不需要任何像 Bellman-Ford 或 Dijkstra 这样的花哨算法 - 我们只需要生成所有 length=3 路径并过滤端点。
# to find desired inputs
# treat each state as a node in a graph
# (think of visual graph transition diagrams)
# and add edges between them labeled with the inputs
# find all l=3 paths, and check the end nodes
nodes = {format_boolvec(prod): {} for prod in itertools.product([False,True], repeat = 6)}
for index, row in df.iterrows():
nodes[row['v(t)']][row['U']] = row['v(t+1)']
# we now built the graph, only need to find a path from start state to end state
def prefix_paths(prefix, paths):
# aux helper function for all_length_n_paths
for path, endp in paths:
yield ([prefix]+path, endp)
def all_length_n_paths(graph, start_node, n):
"""Return all length n paths from a given starting point
Yield tuples (path, endpoint) where path is a list of strings of the inputs, and endpoint is the end of the path.
Uses internal recursion to generate paths"""
if n == 0:
yield ([], start_node)
return
for inp, nextstate in graph[start_node].items():
yield from prefix_paths(inp, all_length_n_paths(graph, nextstate, n-1))
# just iterate over all length=3 paths starting at 101100 and print it if it end's up at 011001
for path, end in all_length_n_paths(nodes, "101100", 3):
if end=="011001":
print(path)
这段代码也应该很容易理解,也许除了迭代器语法。
结果不仅仅是一条,而是 3 条不同的路径:
['100', '110', '011']
['101', '110', '011'] ['111', '110', '011']
评论