MENTAL
 Main Menu
 Applications
 Computer Science
 Logic Programming


Logic Programming
 LOGIC
PROGRAMMING

A declarative programming

"Top-down inference unifies problem solving and computer programming" (Robert Kowalski).



The Theory of Logic Programming and the Prolog Language

Logic Programming

The main idea of logic programming is the separation of the logic and the execution mechanism (control), informally expressed by Robert Kowalski [1979] by means of Logic specifies the "what". Control specifies the "how".

The intended purpose of this separation is that the programmer specifies what is known (the logical relationships) and that it is the system that automatically responds to possible queries posed to the Knowledge Base.

In traditional imperative languages: On the other hand, in logic programming-oriented languages, the situation is the opposite:
Clausal logic

Logic programming is based on clausal logic, which is a restriction of first-order predicate logic in which the logical expressions (clauses) are of conditional type and have the following form: the antecedent is of n terms connected by the logical operator "and" and the consequent consists of only one term. These are the so-called "Horn clauses" [1951], after Alfred Horn, who studied them, and they have the form The expression h is called the "header" of the clause. The set of expressions ci is called the "body" of the clause and are the necessary conditions for the consequent to be verified. The commas between the conditions are interpreted as logical "and".

In Horn clauses there are no explicit quantifiers. Free variables are considered to be universally quantified.

There can be several Horn clauses with the same header. This means that the expression h can be reached in alternative ways, i.e., it would be equivalent to the classical logical operator "or".

A fact can be considered a particular case of Horn clause when the antecedent does not exist (only consequent exists).

Since in classical logic we define AB = ¬AB and since De Morgan's law ¬(AB) = ¬A∨¬B is satisfied, a Horn's clause is

c1, c2, ..., cnh = ¬ (c1 ∧ ... ∧ cn) ∨ h = ¬c1 ∨ ... ∨ ¬cnh

A logical expression consisting exclusively of disjunctions is simply called a "clause", where a term and its opposite (or complement) cannot appear, because if they did appear, the clause would be a tautology.

According to classical logic, any logical formula can be expressed in disjunctive normal form (disjunction of conjunctions) or in conjunctive normal form (conjunction of disjunctions). Therefore, a logical formula can be expressed as a conjunction of clauses.

A clause in normal form is a clause in Skolem normal form: existential quantifiers have been made universal by ∃x P(x) = ¬∀x ¬P(x ), where all universal quantifiers appear at the beginning of the expression (prenex form), and where universal quantifiers are eliminated as the variables are considered to be universally quantified.

Inference processes in logic programming are based on classulas and on the "unification" and "resolution" principles of John Alan Robinson [1965].


Unification

Unification is a pattern matching process. Unification attempts to identify expressions by substituting variables (xyz) for constants (abc). The unification operator is the substitution operator (=). Two expressions (containing variables) are unified if they have a common expression. Examples: It is not necessary to calculate all possible unifiers. It is sufficient to consider the most general unifier, that is, a unifier such that any other unifier can be obtained by instantiating it. In the last example, the most general unifier is x = y = z = a.

The described unification is of first order. Higher order unification is when the variables represent functions.

Robinson introduced unification as a basic operation of his solving principle and developed an algorithm to compute the most general unifier. Robinson's first unification algorithm [1971] was inefficient. Subsequently, more efficient algorithms have been proposed.


Resolution

Resolution is a generalized inference rule that infers a new clause from two clauses containing complementary terms (one is the negation of the other). Formally: The new clause produced (output) is called "resolvent" of the input clauses, in which the complementary terms disappear.

The resolvent rule is a generalization of modus ponens: Indeed, since AB is defined as ¬AB, applying the resolution rule: Examples:
  1. From pqr and from ¬r is inferred pq.
  2. From p and ¬p we infer □ (the empty clause), which indicates contradiction.
In first-order predicate logic, the resolution rule is: In clausal form, In first-order predicate logic, a unification process is performed. In this case, the unification is x = a. This rule is the one that governs in the syllogism.

SyllogismLogical ExpressionClauseBB
Everything x that is P, is Qx P (x) → Q(x)¬P(x) ∨ Q(x)
a es PP(a)P(a)
a es QQ(a)Q(a)

The resolution rule also takes this other form: In clausal form, In this case there is no unification. This rule is the one that governs in the syllogism.

SyllogismLogical expressionClause.
Everything x that is P, is Qx P (x) → Q(x)¬P(x) ∨ Q(x)
All x which is P, is Rx Q (x) → R(x)¬Q(x) ∨ R(x)
All x which is P, is Rx P (x) → R(x)¬P(x) ∨ R(x)


Hiper-resolución

Hyper-resolution is a generalization of resolution in which several resolution steps are combined into one. Basic hyper-resolution consists of splitting the cliques into nuclei and electrons. Nuclei have at least one negative term. Electrons have all positive terms. Hyper-resolution occurs between a nucleus and one or more electrons. There is one electron for each negative term of the nucleus. An electron can be used in more than one intermediate step. Example: Generalized hyper-resolution consists of considering clauses containing pairs of complementary terms to eliminate them at once. For example:
Resolution by refutation

The resolution rule is also used for the proof of theorems by reductio ad absurdum (resolution by refutation). It is a bottom-up type process (bottom-up): For example, if we have the Knowledge Base We want to prove S: Some Dog barks: ∃x Barks(x)
  1. We convert the Knowledge Base and the ¬S statement into clauses:.

      Dog(x) → Bark(x) = ¬Dog(x) ∨ Bark(x)
      Dog(Pancho)
      ¬∃x Ladra(x) = ∀x ¬Ladra(x) = ¬Ladra(x).

  2. Applying the resolution to the complementary terms Ladra(x) and ¬Ladra(x), of the first and third clauses, we obtain as resolvent clause ¬Dog(x).

  3. Applying the resolution again to the clauses ¬Perro(x) and Perro(Pancho), we obtain the empty clause (□). Therefore, the clause S is true.
Another example. We have a Knowledge Base formed by the clauses We want to prove r. We add ¬r as a new clause. Then we have: Therefore, r is true.


The Prolog language

The best known logic programming language is Prolog, which is based on two main concepts:
  1. Clausal logic.
    A Prolog program consists of a series of Horn clauses that state the facts and rules of inference. It is the so-called "Knowledge Base".

  2. Automatic inferences.
    It is the control or process associated to how the language obtains the answer to a query related to a Knowledge Base. Inferences are based on the principles of unification and resolution.

    Inferences can be of two types: 1) forward chaining (deductive, data-driven); 2) backward chaining (inductive, goal-driven). These inferences are also called top-down and bottom-up, respectively.

    Forward inference is the simplest. Backward inference requires a more elaborate process. It consists of stating a goal. Horn's clauses are used to search for the target as a consequent. Once located, the target is replaced by the body of the clause (the antecedent). Each of the conditions of the antecedent are converted into sub-objectives, to which the same mechanism is applied, and so on until all the conditions are met. In the process, all Horn clauses in which the same consequent (objective or subobjective) appears must be considered. The final result is the composition of all the substitutions made.
The limitations of Prolog are:
Logic Programming with MENTAL

The notation of predicates

In predicate logic, the notation P(x1, ... , xn), where P is the predicate and x1, ... , xn are the arguments involved in the predicate (n-ary). When n is greater than one, this notation does not clearly reflect the semantic relations of the arguments to the predicate nor the relations of the arguments to each other.

With one argument, there is no problem: Man(Pepe) indicates that Pepe is a man. With two arguments, problems appear: in Father(Pepe, David) it is intuited that it indicates that Pepe is David's father, but the expression does not reflect this. With three arguments, the situation becomes more complicated.

The clearest notation is the one that makes use of MENTAL primitives. Examples: Pepe's children could be specified in a single expression: But the relation "Father" is ascending, which forces to specify in 4 expressions the four children of Pepe or to use the distribution operator. It is simpler to use the descending notation and specify Pepe's children in one expression: This functional type notation has the advantage that it also allows the use of several arguments. For example, With Pepe/man and Pili/woman.


Knowledge Base

A Knowledge Base consists of:
  1. Specific knowledge. In classical terminology, a Factual Basis. It is specified by

    ( Facts = ( h1...hn ) )

    Being the hi concrete facts.

  2. Generic knowledge. In the classical approach, they are represented by a set of rules:

    ( Rules = ( r1...rm ) ) )

    Being the ri concrete rules.

    The expression of a Horn clause is in MENTAL especially homogeneous:

    ⟨ (c1 → c2 → ... → cm) ⟩

    In a compact form, it can be expressed as follows: ⟨ →⊣( c1...cm ) ⟩

    Specifies that if the conditions c1, ... , c(m−1) are satisfied, then cm is satisfied. This last element we can call the "terminal element" of a Horn clause.

    But in MENTAL it is not restricted to Horn clauses nor only to rules. The possible expressions are limited only by primitives.

Knowledge Base Example
  1. Specific knowledge (facts).

    ( Sons(Pepe Pili) = {JoséJuan Natalia Eva David} )

    ( Pepe/man Pili/woman )

    ( JoséJuan/man Natalia/woman Eva/woman David/man )

    ( Children(Juanjo Natalia) = {Jorge Cristina} )

    ( Juanjo/man Jorge/man Cristina/woman )


  2. Generic knowledge (rules):

    ⟨( (x ∈ Children(y z)) → ((Father(x) = y) (Mother(x) = z))↓ )⟩

    ⟨( {x y}/Siblings ← ((Father(x) = Father(y) ∧ (Mother(x) = Mother(y)) ∧ xy )⟩


    Two persons are siblings if they have the same parents or parents (Prog).

    ⟨( (Parent(x) = y) → (y/(Prog(x)) )⟩

    ⟨( (Mother(x) = y) → (y/(Prog(x)) )⟩


    The consequents indicate that y is a parent of x. Prog(x) is a qualifier of y.

  3. In addition we can define classes, which are used to perform queries. Examples:

    ⟨( (Siblings(x) = Children(Father(x) Mother(x)) ∪' {x} )⟩

    ⟨( (Prog(x) = {⟨( yy/(Prog(x))) )⟩} )⟩

    ⟨( (Ascendants(x) = {⟨( (y z)↓ ← (x ∈ Offspring(y z)) )⟩} ∪ Ascendants(y) ∪ Ascendants(z) )⟩

    ⟨( (Descendants(x) = {⟨( y ← ((y ∈ Children(x z) ∨ (y ∈ Sons(z x)) )⟩} ∪ Descendants(y) )⟩

The automatic top-down inference process

The advantage of generic expressions is that, from the initial data (the facts), some results are generated, which feed the generic expressions, which again produce new results, and so on until the results stabilize. This whole process takes place automatically.
  1. Rule:
    ⟨( (x ∈ Sons(y z)) → ((Father(x) = y) (Mother(x) = z))↓ )⟩

    Results:

    Father(JoséJuan) = Pepe) (Mother(JoséJuan) = Pili)
    Father(Natalia) = Pepe) (Mother(Natalia) = Pili)
    Father(Eva) = Pepe) (Mother(Eva) = Pili)
    Father(David) = Pepe) (Mother(David) = Pili)
    Father(Jorge) = Juanjo) (Mother(Cristina) = Natalia)


  2. Rule:
    ⟨( {x y}/Siblings ← ((Father(x) = Father(y) ∧ (Mother(x) = Mother(y)) ∧ xy )⟩

    Results (combinations of siblings taken 2 by 2):

    {JoséJuan Natalia}/Siblings
    {JoséJuan Eva}/Siblings
    {JoséJuan David}/Siblings
    {Natalia Eva}/Siblings
    {Natalia David}/Siblings
    {Eva David}/Siblings
    {Jorge Cristina}/Siblings


  3. Rule:
    ⟨( (Parent(x) = y) → (y/(Prog(x)) )⟩

    Results:

    Pepe/(Prog(JoséJuan))
    Pepe/(Prog(Natalia))
    Pepe/(Prog(Eva))
    Pepe/(Prog(David))
    Juanjo/(Prog(Jorge))
    Juanjo/(Prog(Cristina))


  4. Rule:
    ⟨( (Mother(x) = y) → (y/(Prog(x)) )⟩

    Results:

    Pili/(Prog(JoséJuan))
    Pili/(Prog(Natalia))
    Pili/(Prog(Eva))
    Pili/(Prog(David))
    Natalia/(Prog(Jorge))
    Natalia/(Prog(Cristina))

Knowledge Base Query

Once new results have been generated from the facts and rules, queries can be performed. Queries can be of the selection type or the verification type.

Examples of selection:
  1. Who are Pepe's children?
    Sons(Pepe) // ev. {JoséJuan Natalia Eva David}

  2. Who are Pepe's descendants?
    Descendants(Pepe) // ev. {JoséJuan Natalia Eva David Jorge Cristina}

  3. Who are Jorge's ancestors?
    Ascendants(Jorge) // ev. {Pepe Pili Juanjo Natalia}

  4. Who are David's siblings?
    Brothers(David) // ev. {JosephJohn Natalia Eve}

  5. Who are David's parents?
    Prog(David) // ev. {Pepe Pili}

  6. What are the parents with 2 or more children?
    {⟨( (x y)↓ ← (Children(x y))# ≥ 2 )⟩} // ev. {Pepe Pili Juanjo Natalia}
Verification examples:
  1. Pepe is male?
    (Pepe/Man)? // ev. α
    Pepe/Man is in the Fact Base.

  2. What are Pepe's children?
    Sons(Pepe) // ev. {JoséJuan Natalia Eva David}
    Hijos(Pepe) is also in the Fact Base.

  3. Is Pepe the father of David?
    (Father(David) = Pepe)? // ev. α

  4. Are David and Jorge brothers?
    ({David George}/Brothers)? // ev. θ
If clearer answers are desired, we can do:

( (True =: α)(False =: θ) )
(Pepe/man)? // ev. True
(Pepe/woman)? // ev. False



Other attributes

It is also possible to assign other attributes (e.g. numeric) and perform queries, as in Databases. For example, we add the attribute AñoNac (Year of Birth) to Pepe's children in the Fact Base: Who are Pepe's children born in 1970 or later?
Resolution rule

In MENTAL, the resolution rule takes the following form: That is, two disjunctive expressions of the abstract spacui containing two opposite terms are replaced by a single one, at all times. The two merging expressions have no relation to each other. They only share the property of belonging to the environment.

This rule is general, valid for all types of expressions x, y, z, whether propositions or predicate logic expressions of any order. It is also a generalized hyper-resolution rule for propositional clausal logic. For example, the clauses They are solved in two steps:
  1. ¬P∨¬Q∨R and Q∨C are transformed into ¬P∨R∨C.
  2. ¬P∨R∨C and P∨D become R∨C∨D.
This is another demonstration of the power of generic expressions.


Advantages of MENTAL as a logic programming language In conclusion, all the complexity of traditional logic programming lies in:

Addenda

On Robinson's principle of resolution

The resolution principle was proposed by Robinson in the 1965 publication "A Machine-Oriented Logic Based on the Resolution Principle" as a foundation for the automatic proof of theorems. Since then, this principle has been applied generally in AI (artificial intelligence).

His method of unification and resolution largely eliminated the combinatorial explosion that occurs in automatic theorem proving, the excessive number of clauses generated, the so-called "Herbrand universes". Actually, the resolution principle rather than "inferring", what it does is to "merge" two clauses into one, with the consequent saving of memory and processing time.

Robinson paved the way for logic programming in general and for the Prolog language in particular.

In Intel, AMD and other microprocessors, an automatic theorem prover (with Robinson's resolution) is used to verify that mathematical operations have been designed correctly.


More information about Prolog

The name "Prolog" comes from "Logic Programming" and was developed in the 1970s by Alain Colmerauer and his team at the University of Marseille, largely inspired by the work on logic programming of Robert Kowalski [1979], who in turn was inspired by Robinson's concepts of unification and resolution by refutation.

The control mechanism uses a backward chaining inference method, since in order to verify a certain initial expression (or objective), the system has to verify whether all the conditions on which it depends (subobjectives) are satisfied, which in turn may or may not depend on other conditions, and so on. What you have in short is a tree in which a depth-first search is performed. The Prolog language has had a great influence on AI. It caused a split between the "Prologists" (the supporters of Prolog) and the "Lispists" (the supporters of Lisp). It is the confrontation between two paradigms: the logical (Prolog) and the functional (Lisp). MENTAL is a language that contemplates, in a simple way, both paradigms and many more. It is a universal paradigm that allows expressing particular paradigms. [see Applications - Artificial Intelligence - MENTAL, an Artificial Intelligence Language].

Prolog has been applied in numerous fields: natural language processing, compiler development, expert systems, pattern search, automatic reasoning, automatic theorem proving, etc.

There are numerous dialects of Prolog, some with particular control mechanisms. The so-called "Edinburgh Prolog" is the "de facto" standardized dialect. There are also "post-Prolog" languages, with more advanced concepts, such as Prolog, which uses an extension of clausal logic and higher-order unification.

Prolog became in the 1980s the official language of the Japanese fifth-generation computer project, based on AI, with parallel processing hardware and Prolog as the logic language for automatic reasoning. The project was cancelled in 1993, after 11 years of development.


Bibliography