【学习笔记】1-两个小demo---sentence generate与 water pouring

1. 背景

    跟踪学习某平台培训课程,写个笔记记录一下。刚听了第一节课,属于导论性质,通过两个小案例,大致描述了一下ai的思想和想要解决的问题,特此记录。工作之后,时间比较紧张,有段时间没有更新博客了,争取后续会坚持把学习的内容记录下来吧。

2. 案例

    导论课大致讲了两个案例:1.基于语法规则匹配的句子生成;即:定义一些语法句式,目标是改变输入的情况下,不更改代码,得到输出(想阐述的是AI的一般思想,就是面对不同输入,通过模型,得到正确输出)。2.基于动态规划思想的倒水问题;即:两个不同容量的杯子,每次只操作一个杯子,如何得到目标水量。

2.1 句子生成

    依据规则,随机生成句子。后续可拓展为,生成多个句子,依据概率判断生成的句子是否合理。

# coding=utf-8
import random

rules = """
复合句子 = 句子 , 连词 复合句子 | 句子
连词 = 而且 | 但是 | 不过
句子 = 主语 谓语 宾语
主语 = 你| 我 | 他 
谓语 = 吃| 玩 
宾语 = 桃子| 皮球
"""

def get_grammer_by_rules(rules):
    # 按照规则拆分规则。分成句子成分,及各成分对应的词集合
    rule_pattern = [rule.split('=') for rule in rules.split("\n") if rule.strip()]

    # 构造规则对应的语法。构造成 句子成分:[, , ,] 的形式
    grammer = {head.strip(): collects.split('|') for head, collects in rule_pattern}

    return grammer

def get_sentence_by_grammer(grammer, target='句子'):

    # 生成目标和语法不匹配
    if target not in grammer:
        return target

    # 迭代符合句子里面的子句子,如果item为子句子,则再分割一次; 其他直接返回对应的值
    sentence = ''.join([get_sentence_by_grammer(grammer, item) for item in random.choice(grammer[target]).split()])
    return sentence

def main():
    # 1. 依据描述(规则)生成对应的语法描述
    rule_grammer = get_grammer_by_rules(rules)

    # 2. 根据规则生成句子
    sentence = get_sentence_by_grammer(rule_grammer, target='复合句子')

    # TODO: 生成若干个句子,根据概率,判断句子的合理性;对应排除不合理的句子。
    print(sentence)

if __name__ == '__main__':
    main()

2.2 water pouring

# coding=utf-8

"""
需求:有两个容量不同的杯子,根据杯子容量的差别,每次操作一个杯子;
构造不同目标量

思路:1.根据杯子当前状态,列出所有可能的操作,以此确定杯子的下一状态
    x, y : 杯子当前水量
    X, Y : 杯子容量
    操作:
    (x, 0): y杯子水倒空(水量为0)
    (0, y): x杯子水倒空
    (x, Y): y杯子装满(水量为Y)
    (X, y): X杯子装满(水量为X)
    (x+y-Y, Y) if x+y > Y else (0, x+y): 将x重的水倒入y中
    (X, x+y-X) if x+y > X else (x+y, 0): 将y重的水倒入x中

    2.如果目标量,正好是 1 中的某种状态,返回对应的操作;
    否则,迭代,继续探索某次操作后的水量的对应状态
"""

def get_stats(x, y, X, Y):

    return {
        (x, 0): '倒空y',
        (0, y): '倒空x',
        (x, Y): '灌满Y',
        (X, y): '灌满X',
        ((x+y-Y, Y) if x+y >= Y else (0, x+y)): 'X->Y',
        ((X, x+y-X) if x+y >= X else (x+y, 0)): 'Y->X',
    }

def solution(c1, c2, goal, start=(0, 0)):
    """
    :param c1: 杯子1的容量
    :param c2: 杯子2的容量
    :param goal: 构造目标
    :param start: 两个杯子初始的水量
    :return: list 方案
    """
    if goal in start:
        return [start]

    explored = set()
    froniter = [ [('init', start)] ]

    while froniter:
        path = froniter.pop(0)

        # 当前杯子中的水量
        x, y = path[-1][-1]
        for state, action in get_stats(x, y, c1, c2).items():
            if state not in explored:
                explored.add(state)
                path_ = path + [(action, state)]

                if goal in state:
                    return path_
                else:
                    froniter.append(path_)

    return []

def main():

    # 1. 定义杯子的可能状态(操作),并返回
    # get_stats()

    # 2. 解决方案
    res = solution(9, 4, 6, start=(0, 0))
    print(res)

if __name__ == '__main__':
    main()

3. 总结

  • 两个案例很小,有点过时了,但是思想还是不错的。句子生成的例子中,阐述一般AI的思想就是面对变化的输入,代码(模型)不变,期望得到较好的输出;water pouring 的例子中,阐述了一点点动态规划的思想,利用当前阶段的可能状态,指导下一状态的生成。
  • 代码中很巧妙的运用了迭代的实现,值得思考。
posted @ 2021-04-28 17:34  温良Miner  阅读(92)  评论(0编辑  收藏  举报
分享到: