在 python 字典中使用 DFS 评估布尔逻辑
Evaluate boolean logic using DFS in python dict
我的字典结构如下所示:
{
"condition": "AND",
"rules": [
{
"id": "monitor_category",
"field": "monitor_category",
"type": "string",
"input": "select",
"operator": "equal",
"value": "Competition",
"decision": True
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "PassiveTotal",
"decision": True
},
{
"condition": "OR",
"rules": [
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Attack",
"decision": False
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Hunt",
"decision": True
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Threat",
"decision": False
}
]
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "Analysis",
"decision": False
}
]
}
对于每条规则,我得出一个决定并将其附加到策略规则。我通过字典的简单递归遍历来做到这一点。在上面的示例策略中,布尔逻辑等同于以下内容:
(True and True and (False or True or False) and False)
我想要一个函数,它采用此策略并能够导出布尔逻辑,以便 return 进行最终评估。我知道深度搜索优先方法可能是这里的方向,但我正在努力解决如何保持布尔状态并知道我在结构中处于哪个级别。
创建一个字典来保存functions that correspond to 'conditions'
import operator, functools
operations = {'AND':operator.and_, 'OR':operator.or_, 'XOR':operator.xor}
编写一个递归函数,当 'conditions'
是规则中的键时递归,否则遍历规则并在列表中累积 'decisions'
。使用 functools.reduce
将 condition
应用于决策。
def f(d):
func = operations.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return functools.reduce(func, decisions)
if func is None: return
本来是基本情况,但我不太确定是否需要它 - 如果发生这种情况,dict 就会搞砸,它可能应该引发 ValueError
我认为这有一个隐含的基本情况(如果有这样的事情) - 它依赖于 for rule in d['rules']:
循环到 运行 out of items.
如果条件限于'AND'和'OR'可以使用all
和any
。
ops = {'AND':all, 'OR':any}
def g(d):
func = ops.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return func(decisions)
我的字典结构如下所示:
{
"condition": "AND",
"rules": [
{
"id": "monitor_category",
"field": "monitor_category",
"type": "string",
"input": "select",
"operator": "equal",
"value": "Competition",
"decision": True
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "PassiveTotal",
"decision": True
},
{
"condition": "OR",
"rules": [
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Attack",
"decision": False
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Hunt",
"decision": True
},
{
"id": "article_tag",
"field": "article_tag",
"type": "string",
"input": "text",
"operator": "contains",
"value": "Threat",
"decision": False
}
]
},
{
"id": "monitor_tag",
"field": "monitor_tag",
"type": "string",
"input": "text",
"operator": "equal",
"value": "Analysis",
"decision": False
}
]
}
对于每条规则,我得出一个决定并将其附加到策略规则。我通过字典的简单递归遍历来做到这一点。在上面的示例策略中,布尔逻辑等同于以下内容:
(True and True and (False or True or False) and False)
我想要一个函数,它采用此策略并能够导出布尔逻辑,以便 return 进行最终评估。我知道深度搜索优先方法可能是这里的方向,但我正在努力解决如何保持布尔状态并知道我在结构中处于哪个级别。
创建一个字典来保存functions that correspond to 'conditions'
import operator, functools
operations = {'AND':operator.and_, 'OR':operator.or_, 'XOR':operator.xor}
编写一个递归函数,当 'conditions'
是规则中的键时递归,否则遍历规则并在列表中累积 'decisions'
。使用 functools.reduce
将 condition
应用于决策。
def f(d):
func = operations.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return functools.reduce(func, decisions)
if func is None: return
本来是基本情况,但我不太确定是否需要它 - 如果发生这种情况,dict 就会搞砸,它可能应该引发 ValueError
我认为这有一个隐含的基本情况(如果有这样的事情) - 它依赖于 for rule in d['rules']:
循环到 运行 out of items.
如果条件限于'AND'和'OR'可以使用all
和any
。
ops = {'AND':all, 'OR':any}
def g(d):
func = ops.get(d['condition'], None)
if func is None:
return
decisions = []
for rule in d['rules']:
if 'condition' in rule:
decision = f(rule)
else:
decision = rule['decision']
decisions.append(decision)
return func(decisions)