Python 将每个变量替换为与其关联的特定值

Python 将每个变量替换为与其关联的特定值,python,pattern-matching,artificial-intelligence,Python,Pattern Matching,Artificial Intelligence,对于一所大学的项目,我正在开发一个用Python编写的推理机,我试图在其中介绍Clips的所有特性,其中之一就是变量 实际上,在语法中,我提供了一种方法,以便在规则中指定一个条件,其中包含使用“?”字符的变量。特别是,我可以这样定义规则: (rule (father ?x ?y) then (assert (parent ?x ?y)) 假设工作记忆中存在以下事实: (father John Tom) (father John Liz) (father Alex Mat) (father Al

对于一所大学的项目,我正在开发一个用Python编写的推理机,我试图在其中介绍Clips的所有特性,其中之一就是变量

实际上,在语法中,我提供了一种方法,以便在规则中指定一个条件,其中包含使用“?”字符的变量。特别是,我可以这样定义规则:

(rule (father ?x ?y) then (assert (parent ?x ?y))
假设工作记忆中存在以下事实:

(father John Tom) (father John Liz) (father Alex Mat) (father Alex Andrew)
根据定义的规则,我们只需进行一些变量模式匹配即可断言这些事实:

(parent John Tom) (parent John Liz) (parent Alex Mat) (parent Alex Andrew)
在这种情况下,我是,实际上我能够正确地将每个变量与WM中存在的所有可能值匹配

在本例中,我创建了一个字典,其键是变量的标识符(?x或?y),其值是WM中存在的所有值,这些值可以与变量关联
(例如{x:[John,Alex],-y:[Tom,Liz,Andrew]})

我的问题是: 如何以正确的方式正确处理所有变量的可能值,以获得所有应该断言的事实

提前谢谢大家,


亚历山德罗·苏格里亚

也许是这样的吧

bank = { ("John","Tom"): ("father", "parent"),
         ("John","Liz"): ("father", "parent"),
         ("Alex","Mat"): ("father", "parent"),
         ("Alex","Andrew"): ("father",)}

x = ("John", "Alex")
y = ("Tom","Liz","Mat","Andrew")

def assert_then_xy(trait1, trait2):
    for my_x in x:
        for my_y in y:
            if (my_x,my_y) in bank.keys():
                if trait1 in bank[my_x,my_y] and not trait2 in bank[my_x,my_y]:
                    print "{} {} is a {}, but not a {}".format(my_x,my_y,trait1,trait2)
            else:
                print "{} {} could not be located".format(my_x,my_y)

>>> assert_then_xy("father", "parent")
John Mat could not be located
John Andrew could not be located
Alex Tom could not be located
Alex Liz could not be located
Alex Andrew is a father, but not a parent
>>> assert_then_xy("parent", "father")
John Mat could not be located
John Andrew could not be located
Alex Tom could not be located
Alex Liz could not be located
>>> 

我已经找到了一个使用递归函数来解决这个问题的方法,我在这里简要地描述了这个函数,以供以后关于这个主题的问题参考

def substitute_var_rec(solutions, var_dict, curr_list, missing_var, var_index):
'''
    solutions: list which contains all the correct combinations generated
    curr_list: list which contains the current combination
    missing_var: variables not yet replaced
    var_index: variables' position in the pattern (a dictionary whose keys are variables'
    identifier and which has as values a list of index)

'''

# if the current combination doesn't contains variable 
# we have finished the construction of the current combination
if not has_variable(curr_list):
    # add it to the solutions' list
    solutions.append(curr_list[:])

else:
    next_var = missing_var[0]  # take the next variable to be examined
    for val in var_dict[next_var]:
        index = var_index[next_var]
        if isinstance(index, list):
            for curr_index in index:
                curr_list[curr_index] = val
        else:
            curr_list[var_index[next_var]] = val
        substitute_var_rec(solutions, var_dict, curr_list, missing_var[1:], var_index)


def substitute_variable(fact, var_dict):
    '''
        fact: a list which contains the fact's name and its attributes
        var_dict: mapping between variables' identifiers and their values
    '''
    pattern = fact[1:]  # a list which contains the pattern to be filled with variables' values
    variables = [x for x in pattern if x.startswith('?')] # takes variables's identifier
    if len(variables) > 1: # different variables in fact
        first_variable = variables[0] 
        all_solutions = []

        # generates a dictionary which contains the variables' position in the pattern
        var_index = {}
        for i in range(len(pattern)):
            if pattern[i].startswith('?'):
                if pattern[i] in var_index:
                    if isinstance(var_index[pattern[i]], list):
                        var_index[pattern[i]].append(i)
                    else:
                        var_index[pattern[i]] = [var_index[pattern[i]], i]
                else:
                    var_index[pattern[i]] = i

        curr_list = pattern[:]

        # starting from the first variable
        # explore all its values and generate all the combinations
        for val in var_dict[first_variable]: 
            index = var_index[first_variable]
            if isinstance(index, list):
                for curr_index in index:
                    curr_list[curr_index] = val
                var_index[first_variable] = index[1:]
            else:
                curr_list[var_index[first_variable]] = val
            substitute_var_rec(all_solutions, var_dict, curr_list, variables[1:], var_index)
            var_index[first_variable] = index
            curr_list = pattern[:]

        return all_solutions
    else:
        var_index = list(pattern).index(variables[0])
        solutions = []

        for val in var_dict[variables[0]]:
            solutions.append([pattern[i] if i != var_index else val for i in range(len(pattern))])

        return solutions
感谢所有回答这个问题的人。 如果你对代码有一些建议,我真的很感激

干杯


亚历山德罗·苏格里亚(Alessandro Suglia)

从字典上看,你不能——你已经失去了配对,无法辨别约翰是汤姆和莉兹的父亲,但亚历克斯是安德鲁的父亲。你需要重新考虑你的数据结构——也许是两个元组?我不明白为什么我不能使用字典。我可以对所有可能的值进行某种组合。如果我有三个变量[x,y,z],每个变量有两个可能的值,我将得到八个可能的解。我说的不对吗?但并非所有这些组合都是正确的<代码>(约翰·利兹神父)(亚历克斯·马特神父)并不意味着
(约翰·马特神父)
是的,当然。事实上,我不想要确切的组合,但我需要某种性格。我曾经考虑过从第一个变量的特定值开始的一个可能的解决方案树,但是我不能正确地重现它,而且我认为它根本不是最好的解决方案,它是错误的。如果你有两个以上的变量,它就不起作用。