Logic programming

Lecture



Features of the Prologue

Prologue is a descriptive programming language used to solve problems in which objects and relations between these objects operate.

Prolog orientation is “unconventional” computer applications: understanding natural language, knowledge bases, expert systems and other tasks.

Its fundamental difference from traditional programming languages ​​lies in the approach to describing the method of solving a problem: the program on Prolog does not describe the procedure for solving the problem, but the logical model of the domain — some facts about the properties of the domain and the relationships between these properties, as well as the rules for deriving new properties and relations from the already specified.

A prologue program consists of sentences, which may be facts, rules, or questions.

Terms of matching terms in the Prolog system

A term is an element of a Prolog program — either a constant, or a variable, or a structure.

A term is written as a sequence of letters, which are divided into 4 categories: {A..Z}, {a..z}, {0..9}, {+ - * / ^ <> ~:. ? @ # $ &}.

The most important term operation is juxtaposition. Matching is the process of checking the comparability of terms.

Two terms are comparable if:

- they are identical,

- variables in both terms can be assigned as values ​​objects in such a way that after substitution they become identical.

For example, date (Day, June, 1999) and date (Day1, June, 1999) are comparable, since the Day and Day1 variables can be assigned the same values ​​from 1 to 31.

General principles for finding answers to questions by the Prolog system

A question in the Prolog system is a sequence of 1 or several goals.

To answer the question, the Prologue tries to achieve all the goals. Reaching a goal is to demonstrate that the goal is true, provided that the relationships in the program are true. Those. demonstrate that the goal follows logically from the facts and rules set in the program.

If the question contains variables, then the Prolog system should find specific objects using which goals are achieved.

Data objects

Data objects in Prolog can be simple data and structures. Simple data can be constants and variables. Constants can be atoms, numbers, and strings.

The prolog system recognizes the type of an object by its syntactic form in the program text.

An atom is a combination of letters, numbers, and underscores, beginning with a lowercase letter. Examples: a, "this_atom", "this_is_atom".

A variable is a combination of letters, numbers, and underscores, beginning with a capital letter. Examples: V, It_variable25.

Structured objects

Structural objects (or simply structures) are objects that consist of several components. These components, in turn, can be structures.

The main characteristic of the structure is its dimension (or arity) - the number of terms in the list.

Structures in the program behave as single objects. In order to combine the components into a structure, it is required to choose a functor (the name of the relation formed between the elements of the structure).

For example, a date can be viewed as a structure consisting of three components: a day, a month, and a year: a date (1, May, 2000).

Program structure

The Turbo Prolog program consists of the following seven sections:

  • compiler directives - additional instructions for processing the program;
  • CONSTANTS - section of the description of constants;
  • DOMAINS - domain description section;
  • DATABASE - the description section of the predicates of the internal database;
  • PREDICATES - section of the description of predicates;
  • CLAUSES - offer description section;
  • GOAL is a section describing an internal target.

The trace directive is used when debugging a program for tracing.

The program does not necessarily have to be all these sections. So, for example, it can consist of one description of a goal:

GOAL

write ("hello"), readchar (_).

As a rule, the program contains at least sections PREDICATES and CLAUSES.

If the program is launched in the Turbo Prolog development environment, then the GOAL section is optional. When writing a program that does not depend on the development environment, it is necessary to indicate an internal goal in it.

The program can have several sections of descriptions DOMAINS, PREDICATES, DATABASE and CLAUSES. However, GOAL sections can not be in the program more than one.

The order of the sections can be arbitrary, but the constants, domains and predicates must be defined before they are used. However, in the DOMAINS section, you can refer to domains that will be announced later.

Arithmetic expressions

Prolog is not intended for programming problems with a large number of arithmetic operations. For this, procedural programming languages ​​are used. However, all usual arithmetic operators are included in any Prolog system:

+ addition,

- subtraction

* multiplication

/ division,

mod remainder of the division of integers

div integer division.

If X is an arithmetic expression, then the list [X] is also an arithmetic expression, for example [1,2,3]. The first element of the list is used as an operand in the expression: X is ([l, 2,3] +5) has the value 6.

Comparing arithmetic expressions

The system predicates =: =, = \ =,>, <,> = and <= are defined as infix operators and are used to compare the results of two arithmetic expressions.

For the predicate @, the proof of the target assertion X @ Y succeeds if the results of calculating the arithmetic expressions X and Y are in such a relation to each other, which is given by the predicate @.

Such a target statement has no side effects and cannot be reconciled. If X or Y are not arithmetic expressions, an error occurs.

Using predicates, the following relationships are described:

X =: = Y X is Y

X = \ = Y X is not equal to Y

X <Y X less Y

X> Y X more Y

X <= Y X less than or equal to Y

X> = Y X is greater than or equal to Y

Work with files

file = <symbolic file name1>; ...;

<symbolic filenameN>

Access to the file can be carried out in two modes - binary and text.

filemode (SymbolicFileName, Mode) is a special predicate for determining the type of file access (the Mode parameter takes one of two values:

0 - Binary Mode,

1 - Text Mode).

The further presentation relates only to working with files in text mode.

In order to work with a file on external media, it must be opened or created. You can open a file for reading, writing, modifying. You can open an almost unlimited number of files, as much as the installation of the operating system allows.

The openread predicate (SimbolicFileName, OSFileName) opens the file as read-only. If the file with the specified external name is not found, the predicate fails and displays an appropriate error message.

The openwrite predicate (SimbolicFileName, OSFileName) opens the file for writing only. This predicate creates a new file on disk. If the file with the specified external name already exists, it will be erased. If for some reason the file cannot be created, the predicate fails and displays an appropriate error message.

The openappend predicate (SimbolicFileName, OSFileName) opens the file only for appending to the end of the file. If the file with the specified name is not found, the predicate displays an appropriate error message.

The openmodify predicate (SimbolicFileName, OSFileName) opens the file for reading and writing at the same time. If the file with the specified name is not found, the predicate displays an appropriate error message.

To check whether the file with the specified name exists in the specified location, the existfile predicate (OSFileName) is used. This predicate has one argument. The predicate is true if the file with the name specified as its only parameter exists and is false otherwise.

These predicates associate the symbolic file name with the physical name of the file being opened.

Since the "\" character, commonly used to separate directory names, is used in Turbo Prolog to write character codes, you need to use two instead of one backslash ("\\"). For example, to specify the path "C: \ Prolog \ BIN", you need to write the string "C: \\ Prolog \\ BIN".

In order to correctly close an open file, the predicate closefile is used. Its only parameter is the symbolic file name. The predicate is successful in any case, even if the corresponding file has not been opened. You can work with the closed file only entirely.

The deletefile predicate (OSFileName) deletes the file specified as its only parameter. If for some reason the file cannot be deleted, this predicate gives an error message.

The renamefile predicate (OldOSFileName, NewOSFileName) changes the name of the file specified as its first parameter to the name specified as its second parameter. If the file whose name is specified in the first parameter does not exist, or the file whose name is specified in the second parameter exists, the predicate will give an error message.

The predicate eof (SymbolicFileName) (short for End Of File - “end of file”) succeeds if the end of the file is reached, otherwise it is unsuccessful. Its only input parameter is the symbolic file name. It is usually used when recursively reading all components of a file. If you try to apply it to the file opened for writing, an error message will be displayed.

The file_str predicate (SymbolicFileName, String) reads the entire file characters into a string or, conversely, writes the contents of the string to a file, depending on whether the second parameter of this predicate is free. The first input parameter of this predicate is the symbolic name of the file, and the second is the string into which the contents of the file are read or from which information is written to it.

The flush predicate (SimbolicFileName) is used to force the contents of the internal buffer allocated for the file specified in its single parameter to be written to the file. It is usually used when working with a printer.

Lists

The list is set by listing the list items separated by commas in square brackets.

List items can be any, including compound objects. In particular, the list items themselves may be lists.

In the domain description section, the lists are described as follows:

DOMAINS

<list domain name> = <list item domain name> *

The asterisk after the domain name indicates that we are describing a list consisting of objects of the corresponding type.

[monday, tuesday, wednesday, thursday, friday, saturday, sunday] - a list whose elements are the English names of the days of the week;

["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] - a list whose elements are the Russian names of the days of the week;

[1, 2, 3, 4, 5, 6, 7] - a list whose elements are the numbers of the days of the week;

['n', 'in', 'c', 'h', 'n', 'c', 'in'] - a list whose elements are the first characters of the Russian names for the days of the week;

[] Is an empty list, i.e. A list that contains no elements (in the Lisp functional programming language, it is denoted by nil).

Recursive list definition

A list is a data structure defined as follows:

  1. an empty list ([]) is a list;
  2. A structure of the form [H | T] is a list, if H is the first element of the list (or several first elements of the list, separated by commas), and T is a list consisting of the remaining elements of the original list.

This definition allows you to organize recursive processing of lists, dividing a non-empty list into head and tail.

Work with lists

The predicate that allows to calculate the length of the list.

length ([], 0). / * no items in empty list * /

length ([_ | T], L): -

length (T, L_T), / * L_T - number

elements in the tail * /

L = L_T + 1. / * L - the number of elements

source list * /

A predicate that allows you to check whether an item belongs to a list (the first argument is the sought value, the second is the list in which the search is performed)

member (X, [X | _]). / * X - the first element of the list * /

member (X, [_ | T]): -

member (X, T). / * X belongs to the tail T * /

A predicate that allows to combine two lists into one . The first two arguments of the predicate will be joined lists, and the third will be the result of a join.

conc ([], L, L). / * when appending an empty list

to list L we get a list of L * /

conc ([H | T], L, [H | T1]): -

conc (T, L, T1). / * connect the tail and the list L, we get

result tail * /

This predicate can be used to solve several problems:

  • to connect lists:
  • ? -conc ([1, 2, 3], [4, 5], X) and X = [1, 2, 3, 4, 5]
  • In order to check if the third list is combined with two lists:
  1. ? -conc ([1, 2, 3], [4, 5], [1, 2, 5]) a No
  2. to split the list into sublists :
  3. Or ask it directly:

last2 ([x], x). / * last element of singleton

list - this item * /

last2 ([_ | L], X): -

last2 (L, X). / * last list item matches

with the last element of the tail * /

A predicate that allows you to write the elements of a list in reverse order (the first argument is the original list, the second is the list resulting from writing the elements of the first argument in reverse order).

reverse ([], []). / * reversing an empty list gives an empty

list*/

reverse ([X | T], Z): -

reverse (T, S), conc (S, [X], Z).

/ * draw tail and attribute to it

right first element of the source

list * /

Another way to reverse:

rev ([H | T], L1, L2): -

rev (T, [H | L1], L2). / * head first

argument we add to

second argument * /

rev ([], l, l). / * if the source list has ended,

then the second argument is passed to the third

argument as result * /

A predicate that allows you to get a list item by its number (the first argument is the source list, the second argument is the number of the element and the third is the list item specified as the first argument of the predicate, having the number specified as the second argument).

n_element ([X | _], 1, X).

n_element ([_ | L], N, Y): -

N1 = N – 1,

n_element (L, N1, Y).

A predicate that checks if an item is a list.

is_list ([_ | _]).

Predicate that converts a list into a single-level one (the first argument is the original list, the second is the result).

simple_list ([], []).

simple_list ([H | List], List1): -

is_list (H), / * if the head of the list is a list, * /

simple_list (H, List1). / * then call recursively

simple_list predicate and pass to it

its as an input parameter * /

simple_list ([H | List], [H | List1]): -

not is_list (H), / * if the head of the list is a simple element, * /

simple_list (List, List1). / * then recursively call

predicate simple_list and write it

to list - result * /

A predicate that removes all occurrences of a given value from the list (the first parameter corresponds to the list to be deleted, the second to the initial value, and the third to the result of removing all the second parameter from the first parameter).

delete_all (_, [], []).

delete_all (X, [X | L], L1): -

delete_all (X, L, L1).

delete_all (X, [Y | L], [Y | L1]): -

X <> Y,

delete_all (X, L, L1).

If you want to remove not all occurrences of a particular value in the list, but only the first , then:

delete_one (_, [], []).

delete_one (X, [X | L], L): - !.

delete_one (X, [Y | L], [Y | L1]): -

delete_one (X, L, L1).

A predicate that adds an element to the list (the first parameter is the inserted element, the second is the original list, and the third is the result).

add (X, L, [X | L]).

But if it becomes necessary to add only if the element is missing , then you can use the rule:

add (X, L, L): - member (X, L),!. add (X, L, [X | L]).

Term Type Check

Built-in predicates for checking types of terms:

atom (X) is true if X is an atom.

integer (X) - true, X-integer.

float (X) is true if X is a real number.

compound (X) is true if X is a compound term.

atomic (X) - true if X is integer or atom.

var (X) is true if X is an unspecified variable.

nonvar (X) is true if an X is a term other than a variable, or an already concretized
variable.

ground (X) is true if X does not contain free variables.

number (X) is true if X is a number.

string (X) is true if X is a string.

Database operations

The prolog program can be considered as a relational database, i.e. description of some set of relationships.

The description of relationships is present either explicitly (facts) or implicitly (rules).

Built-in predicates:

assert (d) is always successful and adds fact d to the database;

retract (d) removes a fact comparable to d;

asserta (d) - provides an entry to the beginning of the database of a new fact for a given relation;

assertz (d) provides a record at the end of the database of a new fact for a given relation.

A dynamic database is declared using the database keyword.

created: 2014-09-30
updated: 2021-03-13
132472



Rating 9 of 10. count vote: 2
Are you satisfied?:



Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Programming Languages and Methods / Translation Theory

Terms: Programming Languages and Methods / Translation Theory