end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

kanren for python による論理プログラミング (素数の判定)

https://www.oreilly.co.jp/books/9784873118727/

上記url の 6章の写経の続き。

「23, 4, 27, 17, 13, 10, 21, 29, 3, 32, 11, 19」から素数を抽出します。

#!/usr/local/python3/bin/python3
# -*- coding: utf-8 -*-
import itertools  # イテレータ関数群
import kanren
from kanren.core import success, fail
import sympy


def main():
    x = kanren.var()

    list_nums = (23, 4, 27, 17, 13, 10, 21, 29, 3, 32, 11, 19)

    print( 'List of primes in the list:' )
    
    # 「membero, x, list_nums」= xに対するlist_numsの要素判定
    # 「check_prime, x」= xに対する素数判定
    # 多分「run(0, ...)」は解を無限に収集し,「run(7, ...)」は解を7個、収集する
    print(
        set(
            kanren.run(0, x, (kanren.membero, x, list_nums), (check_prime, x))
        )
    )


# 素数判定
def check_prime(x):

    if kanren.isvar(x):
        print("X0:",x)
        # 以下の condeseq() により
        # [eq(x,2)] or [eq(x,3)] or [eq(x,5)] or [eq(x,7)] or ...
        # が生成
        # - sympy.ntheory.generate.prime(i)= i番目の素数を算出
        # - it.count(1) = 開始値=1の無限イテレータ
        return kanren.core.condeseq([kanren.eq(x, p)] \
                    for p in map(sympy.ntheory.generate.prime,
                                 itertools.count(1) ))
    print("X1:",x)

    if sympy.ntheory.generate.isprime(x): # 素数判定
        return success
    return fail


if __name__ == '__main__':
    main()

↑こう書くと、↓こう出力されます

$ ./foo.py 
List of primes in the list:
X0: ~_1
X1: 23
X1: 4
X1: 27
X1: 17
X1: 13
X1: 10
X1: 21
X1: 29
X1: 3
X1: 32
X1: 11
X1: 19
{3, 11, 13, 17, 19, 23, 29}

ただ、「if kanren.isvar(x)」内を殆ど通らない点が、気になります。