diff --git a/logic_programming/1_IntroProlog.ipynb b/logic_programming/1_IntroProlog.ipynb index a54008435e7ae2030fddeb66178dc799851679c9..6a638dcc15c0a44759f0780ae190cb772f313ce4 100644 --- a/logic_programming/1_IntroProlog.ipynb +++ b/logic_programming/1_IntroProlog.ipynb @@ -1408,9 +1408,19 @@ "jupyter:print_table(ancestor(X,'Sansa Stark'))" ] }, + { + "cell_type": "markdown", + "id": "e6582326", + "metadata": {}, + "source": [ + "### Send More Money Puzzle\n", + "\n", + "Prolog is also a natural language to solve constraint satisfaction problems. In particular the CLP(FD) library is very useful here. It allows to solve constraints over finite domains." + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 53, "id": "da2e206f", "metadata": { "vscode": { @@ -1418,6 +1428,184 @@ } }, "outputs": [], + "source": [ + ":- use_module(library(clpfd))." + ] + }, + { + "cell_type": "markdown", + "id": "8d8c47ed", + "metadata": {}, + "source": [ + "The library provides a few operators like ```#=```, ```ins``` or ```all_different```:" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "cf4ff4dd", + "metadata": { + "vscode": { + "languageId": "prolog" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[1mX in 0..18,\n", + "Y in 0..9,\n", + "Z in 0..9" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "?- X #= Y+Z, [Y,Z] ins 0..9." + ] + }, + { + "cell_type": "markdown", + "id": "25e2db2a", + "metadata": {}, + "source": [ + "To find solutions one needs to call ```labeling```:" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "4f8aee37", + "metadata": { + "vscode": { + "languageId": "prolog" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[1mX = 0,\n", + "Y = 0,\n", + "Z = 0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "X #= Y+Z, [Y,Z] ins 0..9, labeling([],[Y,Z])." + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "aac2c0ab", + "metadata": { + "vscode": { + "languageId": "prolog" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[1mX = 3,\n", + "Y = 1,\n", + "Z = 2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "X #= Y+Z, [Y,Z] ins 0..9, all_different([X,Y,Z]), labeling([],[Y,Z])." + ] + }, + { + "cell_type": "markdown", + "id": "ae23fbd6", + "metadata": {}, + "source": [ + "Let us now solve the Send More Money puzzle, where we have to find distinct digits such that this equation holds:\n", + "```\n", + " S E N D\n", + "+ M O R E\n", + "= M O N E Y\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "id": "c86fb33e", + "metadata": { + "vscode": { + "languageId": "prolog" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[1mL = [9,5,6,7,1,0,8,2],\n", + "S = 9,\n", + "E = 5,\n", + "N = 6,\n", + "D = 7,\n", + "M = 1,\n", + "O = 0,\n", + "R = 8,\n", + "Y = 2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "?- L = [S,E,N,D,M,O,R,Y],\n", + " L ins 0..9, % all variables are digits\n", + " S#>0, M#>0, % S and M cannot be 1\n", + " all_different(L), % all variables are different\n", + " 1000*S + 100*E + 10*N + D\n", + " + 1000*M + 100*O + 10*R + E\n", + " #= 10000*M + 1000*O + 100*N + 10*E + Y,\n", + " labeling([], L)." + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "deaef138", + "metadata": { + "vscode": { + "languageId": "prolog" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[1;31mERROR: jupyter:retry/0 needs to be the only goal in a term\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "juptyer:retry" + ] + }, + { + "cell_type": "markdown", + "id": "5f251e4d", + "metadata": {}, "source": [] } ],