prolog_如何通过观看权力的游戏学习Prolog

prolog

by Rachel Wiles

瑞秋·威尔斯(Rachel Wiles)

如何通过观看权力的游戏学习Prolog (How to learn Prolog by watching Game of Thrones)

他们死了吗? 他们还活着吗? 她是他的姨妈吗? 不用把精力浪费在2011年,而可以使用Prolog节省精力并建立自己的专家。 (Are they dead? Are they alive? Is she his aunt? Instead of casting your mind back to 2011, save the exhaustion and build your own expert using Prolog.)
权力的强制游戏窒息警告! 所包括的活动到第7季为止,不考虑仅在书籍中发生的任何事情。 如果您不了解最新信息,请谨慎操作。 但是,Prolog自1972年以来一直保持不变,没有剧情曲折,并且易于理解的结构可以使您成功学习本教程。 (Obligatory Game of Thrones SPOILER WARNING! Events included are up to Season 7, disregarding anything that occurs only in the books. If you aren’t up to speed, proceed with caution. But, the Prolog remains the same since 1972, with no plot twists and an easy to follow structure that this tutorial will help you ace.)

确立事实 (Establish the facts)

Prolog is a logic programming language, which forms rules and relationships from facts. To use Prolog, queries are passed through a structured database of facts. Game of Thrones is renowned for its complex (and often incestuous) family trees, so breaking things down into simple facts starts a great basis for a Prolog database.

Prolog是一种逻辑编程语言,可以根据事实形成规则和关系。 要使用Prolog,查询将通过事实的结构化数据库传递。 《权力的游戏》因其复杂的(且经常是乱伦的)家谱而闻名,因此将事物分解为简单的事实就为Prolog数据库奠定了良好的基础。

Simplify things by starting the database with one set of facts, which can be applied to all characters. For family trees, a good place to start is linking characters through their parents. Take the case of Arya Stark:

通过使用一组事实来启动数据库来简化事情,该事实可以应用于所有字符。 对于家谱,一个不错的起点是通过其父母链接角色。 以Arya Stark为例:

parent(eddard_stark, arya_stark).parent(catelyn_stark, arya_stark).

Here, two separate facts have been defined, saying that Eddard and Catelyn are the parents of Arya. You can then extrapolate these queries across the entire Game of Thrones universe, for all the houses, to create a complete database (or, poach the whole dataset from my GitHub). These facts alone are enough to start making queries. The most basic query checks whether a fact is present within the database.

在这里,已经定义了两个不同的事实,说爱达德和卡特琳是艾莉亚的父母。 然后,您可以针对所有房屋在整个《权力的游戏》宇宙中外推这些查询,以创建一个完整的数据库(或者从我的GitHub挖走整个数据集)。 仅这些事实就足以开始进行查询。 最基本的查询检查数据库中是否存在事实。

?-parent(eddard_stark, arya_stark).true

If you input relationships that aren’t within the database, it returns false. You can also query with variables in Prolog by using uppercase. To find who the parents of Arya are, ask:

如果输入的关系不在数据库内,则返回false 。 您也可以使用大写字母在Prolog中查询变量。 若要查找Arya的父母是谁,请询问:

?-parent(Parent, arya_stark).Parent = eddard_stark ;Parent = catelyn_stark.

Eddard returns first in this example, for this is the first true fact listed in the database. Hit semicolon conducts searches for further true answers (catelyn_stark), until there are none remaining. A period terminates the search all together. Use underscores as anonymous variables to filter out information that doesn’t matter. For instance, if you wanted to see that Arya has parents, but don’t care who they are, query the following:

在此示例中,Eddard首先返回,因为这是数据库中列出的第一个真实事实。 命中分号进行进一步的真实答案搜索(catelyn_stark),直到没有剩余答案为止。 句号一起终止搜索。 使用下划线作为匿名变量可以过滤掉无关紧要的信息。 例如,如果您希望看到Arya有父母,但不在乎他们是谁,请查询以下内容:

?-parent(_, arya_stark).true

建立规则 (Create rules)

Now that there are facts in the database, begin creating rules. Rules are dependent on facts. Tying facts together creates rules. From our last example, make a simple rule from the parent fact, to determine a child relationship; X is the child of Y if (written as :- in Prolog) Y is the parent of X.

现在数据库中已有事实,开始创建规则。 规则取决于事实。 将事实捆绑在一起可以创建规则。 在最后一个例子中,根据父事实建立一个简单规则,以确定子关系。 X是Y的孩子,如果 (写为: -在序言)Y是X的父

child(X, Y) :-    parent(Y, X).

This essentially reverses the parent rule, and allows searches up and down the family tree. In another instance, suppose you want to make a rule determined by the absence of a fact…

这实质上颠倒了父规则,并允许在族谱中上下搜索。 在另一种情况下,假设您要制定一个由事实不存在决定的规则……

status(X, dead) :-    not(status(X, alive)).

Here, I’ve expanded the database to include a set of rules for every character that is still alive. The query searches the database for all instances where person X is alive. The not indicates that, if X is not found to be alive, then X is dead. This rule is efficient for Game of Thrones, as it only requires a handful of facts, for the few who are still alive.

在这里,我已经扩展了数据库,以包括针对每个仍然活着的角色的一组规则。 该查询在数据库中搜索X人还活着的所有实例。 表示如果未发现X处于活动状态,则X死亡。 该规则对于《权力的游戏》非常有效,因为它只需要少数事实,而对于少数还活着的人。

More interesting and specific rules are created by combining facts. For example, to create a mother/father relationship, more facts on every character’s gender in Game of Thrones is needed. Once done, a rule to identify mothers is created by the following:

通过结合事实来创建更有趣和更具体的规则。 例如,为了建立父母关系,需要在《权力的游戏》中了解每个角色的性别。 完成后,将通过以下方式创建识别母亲的规则:

mother(X, Y) :-    parent(X, Y),    female(X).

In the above, we’ve stated that a mother (X) is a parent of someone and (written as a comma in Prolog) is female.

在上面,我们已经说过,母亲(X)是某人的父母, 并且 (在Prolog中用逗号表示)是女性。

So far, we’ve covered traveling up and down the family tree, but haven’t touched left to right. By creating a sibling rule, queries can be made every which way across the Game of Thrones family tree:

到目前为止,我们已经介绍了在家谱中上下旅行的过程,但是还没有涉及到从左到右的问题。 通过创建同级规则,可以在《权力的游戏》家族树中的所有位置进行查询:

sibling(X, Y) :-    parent(Z, X),    parent(Z, Y),    dif(X, Y).

In layman’s terms, this states that two people (X and Y) are siblings if they both share the same parent (Z). The dif function here is important to stop the program from returning themselves as their own sibling. HOWEVER, there are limitations to this approach. Querying this will evaluate both parents of X and both parents of Y (often, but not always, the same people), consequently the full search will return duplicates. This can be fixed by introducing lists.

用外行的话说,如果两个人(X和Y)共享同一个父母(Z),则他们是兄弟姐妹。 这里的dif函数对于阻止程序返回自己的同级兄弟很重要。 但是,这种方法有局限性。 查询这将评估X的父母 Y的父母双方(经常,但并非总是如此,同样的人),因此全搜索将返回重复。 这可以通过引入列表来解决。

制作清单 (Making lists)

Revisiting the sibling problem, adding lists will achieve better implementation, and have many applications in Prolog. The code used previously can still be used, however the results need to be collected into a list using the following:

回顾同级问题,添加列表将实现更好的实现,并且在Prolog中具有许多应用程序。 以前使用的代码仍然可以使用,但是需要使用以下命令将结果收集到列表中:

list_siblings(X, Siblings) :-    setof(Y, sibling(X, Y), Siblings);    Siblings = none.

setof pulls together all possible outcomes for the sibling(X, Y)query, and stores them in a list called Siblings. In the case where there are no siblings, the or component (represented by a semicolon in Prolog) returns none. setof also removes any duplicates, keeping only unique values, hence improves the prior query. Now that a list of siblings can be generated for any character, a separate query can determine whether 2 characters are siblings:

setofsibling(X, Y)查询的所有可能结果汇总在一起,并将其存储在名为Siblings的列表中。 在没有同级的情况下, 组件(在Prolog中用分号表示)不返回任何内容。 setof还删除所有重复项,仅保留唯一值,从而改善了先前的查询。 现在可以为任何字符生成同级列表,一个单独的查询可以确定两个字符是否为同级:

siblings(X, Y) :-    list_siblings(X, Siblings),    member(Y, Siblings).

When queried, this builds the list Siblings for X and uses member to determine whether Y is within the list Siblings.

当查询时,这将为X构建兄弟姐妹列表,并使用member来确定Y是否在兄弟姐妹列表中。

Now that there’s sibling relationships, parent relationships and gender within the database, you don’t need to visit the Grand Library in the Citadel to work out who Jon Snow’s aunt is.

现在数据库中存在同级关系,父母关系和性别,您无需访问城堡的大图书馆就可以知道Jon Snow的姑姑是谁。

递归 (Recursion)

The family trees in Game of Thrones span much further than just immediate family. It is possible to venture further out, and generate links between more distant relationships. Using the parent predicate, Prolog can recursively evaluate the database to find ancestry. Setup recursion through including the following 3 sections in a database:

《权力的游戏》中的家谱远不只是直系亲属。 有可能进一步冒险,并在更远的关系之间建立联系。 使用父谓词,Prolog可以递归评估数据库以查找祖先。 通过在数据库中包含以下3个部分来设置递归:

  1. Terminating section — This section must occur before the looping section, to stop the program from looping infinitely:

    终止部分—该部分必须在循环部分之前发生,以阻止程序无限循环:
ancestor(X, Y) :-    parent(X, Y).

2. Looping section — This section calls upon itself repeatedly, until the terminating condition above is met:

2.循环部分-此部分重复调用自己,直到满足上述终止条件为止:

ancestor(X, Y) :-    parent(X, Z),    ancestor(Z, Y).

3. Calling section — query ?-ancestors(X, Ancestor_of) to begin storing a list of ancestors through each recursion as defined above:

3.调用部分—查询?-ancestors(X,Ancestor_of),以开始通过上述每个递归存储祖先列表:

ancestors(X, Ancestor_of) :-    findall(A, ancestor(X, A), Ancestors_of).

The findall function here works similarly to setof, however does not exclude duplicates, and returns a list of who X is the ancestor of.

这里的findall函数与setof相似,但是不排除重复项,并返回X的祖先的列表。

打印和格式化 (Printing and formatting)

If you’re looking for a one stop shop where you can get all information on one character, you’ll need formatting to organise it. To return a bunch of information in one go, call on previously defined rules within a rule:

如果您正在寻找一站式商店,可以在一个字符上获取所有信息,则需要进行格式化以进行组织。 要一次性返回一堆信息,请在规则中调用先前定义的规则:

tell_me_about(X) :-    alive_or_dead(X),    parents(X, Parents),    format("Parents: ~w", [Parents]), nl,     children(X, Children),    format("Children: ~w", [Children]), nl,    list_siblings(X, Siblings),    format("Siblings: ~w", [Siblings]), nl,    !.

format returns whatever output from the square parenthesis in place of the ~w, and prints everything enclosed in quotations. nl represents a new line. The cut function (!) in Prolog prevents backtracking, so forces the program to stop finding additional solutions after the first has been found. In the above, this ensures that everything prints once. Querying this with Stannis Baratheon gives the following:

格式返回方括号中的所有输出来代替〜w,并打印所有用引号引起来的内容。 nl代表换行符。 Prolog中的cut功能( )可以防止回溯,因此在找到第一个解决方案后,强制程序停止寻找其他解决方案。 在上面,这确保所有内容都打印一次。 使用Stannis Baratheon进行查询可以得到以下结果:

The function print can also be used in place of format, when there are no variables to be outputted.

当没有变量要输出时,也可以使用功能打印代替格式。

使用算术 (Using arithmetic)

Arithmetic operations can be used in Prolog to interpret and analyse data. Suppose Arya now wants to be super organised, and use Prolog instead of committing her list to memory. She could use the following to keep track:

可以在Prolog中使用算术运算来解释和分析数据。 假设Arya现在想要被组织得井井有条,并使用Prolog而不是将其列表提交到内存中。 她可以使用以下内容进行跟踪:

aryas_list :-    print("ARYAS TOP SECRET LIST. KEEP OUT."), nl,    findall(X, on_list(X), MainList),    ticked_off(List),    format("Done: ~w", [List]), nl,    not_dead_yet(AnotherList),    format("Still to go: ~w", [AnotherList]), nl,    length(AnotherList, LCompletedList),         length(MainList, LMainList),    Percent is ((LMainList - LCompletedList) / LMainList) * 100,    Percentage is round(Percent),             format("Percentage complete: ~w%", [Percentage]), nl.

In aryas_list, I have used the following operators:

在aryas_list中,我使用了以下运算符:

  • * Multiply

    *相乘
  • - Subtract

    - 减去
  • / Divide

    /除
  • length(). Generate list length

    长度()。 产生清单长度
  • round(). Round to nearest integer

    回合()。 舍入到最接近的整数

The result looks as follows:

结果如下:

With all the tools covered, there’s plenty more interesting ways to explore the Game of Thrones universe in Prolog. Or, scrap watching the show entirely, after working out who should sit on the Iron Throne through inarguable logic programming.

涵盖了所有工具,在Prolog中有许多有趣的方法来探索《权力的游戏》宇宙。 或者,在通过无可辩驳的逻辑编程确定谁应该坐在“铁王座”上之后,完全放弃观看节目。

rightful_heir(X) :-    parent(robert_baratheon, X),    status(X, alive).

The results speak for themselves…

结果不言自明…

If you want to expand the existing database, or play around creating your own relationships, the code is on my GitHub.

如果您想扩展现有数据库或尝试创建自己的关系,请在我的GitHub上找到代码。

Follow my LinkedIn for future projects.

按照我的LinkedIn进行未来的项目。

翻译自: https://www.freecodecamp.org/news/how-to-learn-prolog-by-watching-game-of-thrones-4852ea960017/

prolog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值