Add example of logic programming to find rhymes

main
Eric Ihli 4 years ago
parent 0bd7683020
commit 2a2d5adc35

@ -0,0 +1,158 @@
(ns com.owoga.prhyme.logic.core
(:refer-clojure :exclude [==])
(:require [clojure.core.logic.fd :as fd]
[clojure.string :as string]
[clojure.core.logic.pldb :as db]
[com.owoga.prhyme.data.dictionary :as dict]
[com.owoga.prhyme.syllabify :as syllabify])
(:use [clojure.core.logic]))
(defn productsumo [vars dens sum]
(fresh [vhead vtail dhead dtail product run-sum]
(conde
[(emptyo vars) (== sum 0)]
[(conso vhead vtail vars)
(conso dhead dtail dens)
(fd/* vhead dhead product)
(fd/+ product run-sum sum)
(productsumo vtail dtail run-sum)])))
(defn change [amount denoms]
(let [dens (sort > denoms)
vars (repeatedly (count dens) lvar)]
(run* [q]
(== q (zipmap dens vars))
(everyg #(fd/in % (fd/interval 0 amount)) vars)
(productsumo vars dens amount))))
(change 14 #{1 2 5 10})
(run* [s p o]
(membero s [:mother :child])
(membero o [:mother :child])
(membero p [:loves :has])
(!= s o))
(run* [s p o]
(everyg #(membero % [:mother :child])
[s o])
(membero p [:loves :has])
(distincto [s o]))
(def words-for-db dict/cmu-with-stress)
(defn phonemes-for-rhyme [word-phonemes]
(->> word-phonemes
reverse
(split-with #(re-matches #".*[^1]" %))
(#(concat (first %) (take 1 (second %))))))
(defn perfect-rhyme? [a b]
(= (phonemes-for-rhyme a)
(phonemes-for-rhyme b)))
(defn remove-consonants [w]
(remove #(re-matches #".*[^\d]" %) w))
(defn perfect-vowel-rhyme? [a b]
(= (remove-consonants (phonemes-for-rhyme a))
(remove-consonants (phonemes-for-rhyme b))))
(db/db-rel
word
^:index w
^:index syllable-count
^:index perfect-rhyme-phonemes)
(defn make-word [w]
[word
w
(->> w
rest
(map #(string/replace % #"\d" ""))
syllabify/syllabify
count)
(remove-consonants (phonemes-for-rhyme w))])
(remove-consonants (phonemes-for-rhyme ["po" "P" "AA1" "V" "ER0" "T" "IY0"]))
(def words
(apply
db/db
(map make-word words-for-db)))
(db/with-db words
(run 5 [sentence]
(fresh [w s p
w1 s1 p1]
(== p '("IY0" "OW1"))
(== sentence `(~w ~w1))
(fd/+ s s1 7)
(word w s p)
(word w1 s1 p1)
(== p p1)
(!= w w1))))
(db/db-rel test-word w)
(def test-db (db/db [test-word "hello"]
[test-word "world"]))
(db/with-db test-db
(run 5 [q]
(test-word q)))
(db/db-rel test-word w ^:index pos)
(def test-db (db/db [test-word "hello" :greeting]
[test-word "world" :noun]))
(db/with-db test-db
(run 5 [e a v]
(test-word "hello" a)))
(comment
(run* [q r]
(membero q ["linux" "windows" "mac" "android" ""])
(conda
[fail]
[(membero q ["linux" "windows"]) (== r 1)]
[(== q "mac") (== r 2)]
[succeed (== q "") (== r 3)]))
;; => (["linux" 1] ["windows" 1])
(run* [q r]
(conde
[fail]
[(membero q ["linux" "windows"]) (== r 1)]
[(== q "mac") (== r 2)]
[succeed (== q "") (== r 3)]))
;; => (["mac" 2] ["" 3] ["linux" 1] ["windows" 1])
(run* [q r]
(membero q ["linux" "windows" "mac" "android" ""])
(condu
[(membero q ["linux" "windows"]) (== r 1)]
[(== q "mac") (== r 2)]
[succeed (== q "") (== r 3)]))
;; => (["linux" 1] ["windows" 1] ["mac" 2] ["" 3])
(run* [q r]
(conde
[(membero q ["linux" "windows"]) (membero r ["iOS" "android"])]
[(== q "mac") (== r 2)]
[succeed (== q "") (== r 3)]))
;; => (["linux" "iOS"] ["linux" "android"] ["windows" "iOS"] ["windows" "android"])
(run* [q r]
(condu
[(== q "linux") (== r 1)]
[(membero q ["linux" "windows"]) (membero r ["iOS" "android"])]
[(== q "windows") (== r 2)]
[(== q "linux") (== r 3)]))
;; => (["linux" "iOS"] ["linux" "android"])
)
(let [people (repeatedly 5 lvar)
magazines (repeatedly 5 lvar)
cheeses (repeatedly 5 lvar)
reservations (repeatedly 5 lvar)
answers (map list people magazines cheeses reservations)]
(run* [q]
(== q answers)))
(run* [q]
(fd/in q (apply fd/domain (take 10 (iterate #(* % 2) 1)))))
Loading…
Cancel
Save