AI at minimum salaries 2: Generator of verses on Prolog
The picture shows a quatrain generated by my program.
"" , : , , . "" , , , . , , . : " N ", " ", " " .. , . Prolog — , .
Prolog, .
10
. :
, 9
, , 8
, 9
. 8
, 9
, , 8
, 9
. 8
, 9
, 8
, — 9
. 8
: , 9
, 8
, 9
, 8
, , . , : _'_'_'_'_ ( , — ). . , . , , . . , . , .
. , ( ) ( , ).
-. . , . , , :
,
.
:
- . .
- , .
- . .
- .
- .
- !
:
, 7
. 5
, , 7
— . 5
, . "", .
Prolog
, :
- , .. .
- , .
- .
"" , .. , , , ( ).
: , . - . , , Prolog , .. .
Prolog . , — , .. Prolog , . LISP. Prolog .
Prolog , , . () . , , :
(). () :- ().
Prolog (), (), (). , . , . . Prolog , . , — . " ". :-
.
Prolog ( SWI-Prolog), ?-
. , . socrates.pl [socrates].
,
:
?- (). true.
. , :
?- (). = .
Prolog "". .. (closed-world assumption) — , :
?- (). false.
, , Prolog false.
", ?" — . , . . fib(n, f_n)
,
-
:
fib(0, 1). fib(1, 1). fib(N, F) :- N #> 1, M #= N - 1, K #= M - 1, F #= G + P, fib(M, G), fib(K, P).
, 1. , : " fib(N, F)
, N
, M
N - 1
, K
M - 1
, F
G
P
, fib(M, G)
fib(K, P)
". "". #>
#=
, CLPFD, SWI-Prolog. "" =
, >
.. , REPL ?- use_module(library(clpfd)).
swipl, ?- fib(10, X).
X = 89
. X
, . ';', false
, , X
. : ?- fib(X, 13).
X = 6.
. !
Prolog. ( ) (). : = [ | ]
. , = [1, 2, 3, 4]
, = 1
, = [2, 3, 4]
. . freq(E, L, F)
E
L
F
:
freq(_, [], 0). freq(Element, [Head|Tail], F) :- Head #= Element, F #= P + 1, freq(Element, Tail, P), !. freq(Element, [Head|Tail], F) :- Head #\= Element, freq(Element, Tail, F), !.
: . " " "_". "" , . — . . freq
. ?- freq([1, 2, 2, 3], 2, X)
,
:
X #= X1, Tail = [2, 2, 3] X1 #= X2 + 1, Tail = [2, 3] X3 #= X4 + 1, Tail = [3] X5 #= X6, Tail = [] : freq(_, [], 0), X6 #= 0.
X #= 2
.
. .. "cut operator", . " , freq". -
.
Prolog
Prolog . , , . 3 3. , , , . :
A|B|C 2|7|6 -|-|- -|-|- D|E|F = 9|5|1 -|-|- -|-|- G|H|I 4|3|8
?
- 33 9 .
- .
- .
- 7 , "" .
CLPFD :
magic([A, B, C, D, E, F, G, H, I]) :- Vars = [A, B, C, D, E, F, G, H, I], Vars ins 1..100, all_different(Vars), A + D + G #= B + E + H, B + E + H #= C + F + I, C + F + I #= A + B + C, A + B + C #= D + E + F, D + E + F #= G + H + I, G + H + I #= A + E + I, A + E + I #= C + E + G, label(Vars).
magic
9 [1, 100] . label
. ?- magic(S).
33.
: . . :
- , .. .
- , .
- .
, — . . , , , , . , . :
: : , : : ,
, .
? — :
(, 1). (, 1). (, 3). (, 1). (, 1). (, 1). (, 1). (, 2). (, 2). (, 1). (, 1). (, 3).
. "", , "" . .
:
([, , , ]) :- (, _), (, _), (, _), (, _).
. ?- ().
. ? , ( — , — , — ). — , . :
(, ). (, ). (, ). (, ). (, ).
. , . , " — ", " — " , (, ) — , . , :
- . . .
:
_(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ). _(, ).
"__(1, 2)", 1 2 :
__([], []). __([1|1], [2|2]) :- 1 = 2, __(1, 2). __([1|1], [2|2]) :- _(1, 2), __(1, 2).
: .
, "(1, 2)" :
(1, 2) :- (1, 1), (2, 2), _(1, 1, 1), _(2, 2, 2), atom_chars(1, 1), atom_chars(2, 2), length(1, 1), length(2, 2), 1 - 1 #= 2 - 2, % slice(1, 1, 1, 1), slice(2, 2, 2, 2), __(1, 2), 1 \= 2.
atom_chars
, slice
. : C1 \= C2
, ?- (1, 2).
: . , "" "", "" , "" . "".
, " " "", .. . "".
. . ? , "", "" .
"", :
([1, 1, 1, 1], [2, 2, 2], [3, 3, 3, 3], [4, 4, 4], 1, 2, 3, 4) :- (1, _), (1, _), (1, _), (1, _), _([1, 1, 1, 1], 1), (2, _), 1 \= 2, (2, _), 1 \= 2, (2, _), 1 \= 2, _([2, 2, 2], 2), (3, _), 1 \= 3, (3, _), 1 \= 3, 2 \= 3, (3, _), 2 \= 3, 1 \= 3, (3, _), 2 \= 3, 1 \= 3, _([3, 3, 3, 3], 3), (1, 3), (4, _), 1 \= 4, 3 \= 4, 2 \= 4, (4, _), 1 \= 4, 3 \= 4, 2 \= 4, (4, _), 1 \= 4, 3 \= 4, 2 \= 4, _([4, 4, 4], 4), (2, 4). () :- (, , , , , _, , _), = [, , , ].
( , , ) X \= Y
.
, ?- ().
?
It is clear that everything described is only a proof of concept, you can further develop this topic. For example, add more words to the dictionary, expand the grammar to include different tenses and kinds of words. You can also define new patterns of poems, different from the classics, and indeed the field for experimentation is very rich here.
I hope you enjoyed the article and learned something new. Project repository link: prolog-poetry . There is also a complete launch instruction.