Основные принципы логического программирования

Введение в основные принципы логического программирования [часть 1]

Команда форума подготовила для вас перевод одной очень интересной статьи -> Источник. Приятного чтения!

Логическое программирование — парадигма программирования, основанная на автоматическом доказательстве теорем, а также раздел дискретной математики, изучающий принципы логического вывода информации на основе заданных фактов и правил вывода.(c)Wikipedia

Прежде чем мы поговорим о том, что это такое, и как это относится к искусственному интеллекту, давайте немного поговорим о парадигмах программирования.

Отступление от 5h3ll:

Парадигма программирования, определяет то, как вы будете подходить к решению проблемы. Тут не существует плохой, правильной или не правильной парадигмы, проще всего подобные абстракции, объясняются на примерах из реальной жизни.

Например есть Коля и Петя. Коля строит небольшие сараи на участках, и ход его работ прост, прямолинеен и понятен. Он просто выполняет определенное действие в нужном ему порядке. По сути коля строит сарай используя процедуральную парадигму программирования, причина тому проста — он делал это 1000 раз и тратить время на бесполезное планирование(время деньги) смысла нет.

С другой стороны его друг Петя строит небоскребы в Moscow-City и руководит большим штатом рабочих: архитекторов, юристов, строителей и тд. Понятное дело, что такая большая схема будет крайне неповоротлива, если исполнять все по пунктам. Проблема в том, что пока одно звено не закончит свою функцию — последующее не начнет работу, а это простои работы, финансовые потери ну, и как результат — недовольные инвесторы. Потому лучший выбор для Пети — это: ООП, где все объекты(классы) будут структурированы, заниматься каждый своим делом и в то же время взаимодействовать друг с другом по мере необходимости.

Так что, как мы видим, для каждой проблемы лучше использовать подходящую парадигму.

Вот некоторые из наиболее популярных парадигм программирования:

  • Imperative: в этой парадигме используются операторы для изменения состояния программы, что позволяет учитывать побочные эффекты.
  • Functional: эта парадигма рассматривает вычисления как оценку математических функций и не позволяет изменять состояния или изменяемые данные.
  • Declarative: это способ программирования, при котором вы пишете свои программы путем описывания, что именно вы хотите сделать, а не как вы хотите это сделать. Вы выражаете логику базовых вычислений без явного описания потока управления.
  • Object Oriented: в этой парадигме код группируется в программе таким образом, что каждый объект отвечает за себя. Объекты содержат данные и методы, которые определяют, каким именно образом происходят изменения.
  • Procedural: в этой парадигме код группируется по функциям, и каждая функция отвечает за определенную последовательность шагов.
  • Symbolic: в этой парадигме используется особый стиль синтаксиса и грамматики, с помощью которого программа может изменять свои собственные компоненты, рассматривая их как простые данные.
  • Logic: в этой парадигме вычисления рассматриваются как автоматическое обоснование базы данных знаний, состоящей из фактов и правил.

Чтобы понять логическое программирование, давайте разберемся с понятиями вычислений и дедукций. Чтобы что-то вычислить, мы начнем с выражения и набора правил. Этот набор правил в основном программа. Мы используем эти выражения и правила для генерации вывода.

Например, мы хотим вычислить сумму 23, 12 и 49:

Процедура будет выглядеть следующим образом:

23 + 12 + 49 => (2 + 1 + 4 + 1)4 => 84

С другой стороны, если мы хотим что-то сделать, нам нужно начать с гипотезы. Затем нам нужно построить доказательство в соответствии с набором правил. По сути, процесс вычисления является

механическим, тогда как процесс дедукции более творческий. Когда мы пишем программу в логической парадигме программирования, мы указываем набор утверждений,

основанных на фактах и правилах о проблемной области, и решающая программа решает ее, используя эту информацию.

Понимание составных элементов логического программирования

При программировании объектно-ориентированных или императивных парадигм мы всегда должны указывать, как определяется переменная. В логическом программировании все работает немного иначе.

Мы можем передать неопределенный аргумент функции, и интерпретатор припишет значение этих переменных для нас, взглянув на факты, определенные пользователем. Это мощный способ решения проблемы соответствия переменных. Процесс сопоставления переменных с различными элементами называется унификацией. Это одно из мест, где логическое программирование действительно находится в стороне.

Нам нужно указать то, что называется связи/отношения в логическом программировании. Эти связи определяются с помощью положений, называемых фактами и правилами.

Факты — это просто утверждения, которые являются правдой о нашей программе и данных, с которыми она работает. Синтаксис довольно прост. Например, Дональд — сын Аллана, может быть фактом, тогда как, Кто сын Аллана? не может быть фактом.

Каждая логическая программа нуждается в фактах для работы, чтобы она могла достичь поставленной цели на их основе.

Правила — это та информация, которую мы узнали о том каким образом выражать различные факты и как их запрашивать. Это те ограничения, с которыми нам приходится работать, и они позволяют нам делать выводы о проблемной области.

Например, допустим, вы работаете над созданием шахматного движка. Вам нужно указать все правила о том, как каждая фигура может двигаться на шахматной доске. По сути, окончательный вывод действителен только в том случае, если все отношения/связи верны.

Решение проблем с помощью логического программирования

Логическое программирование ищет решения, используя факты и правила. Нам нужно указать цель для каждой программы. В случае, когда логическая программа и цель не содержат каких-либо переменных,

решающая программа создает дерево, которое представляет собой пространство поиска для решения проблемы и достижения цели.

Одна из самых важных вещей в логическом программировании — это то, как мы относимся к правилам. Правила можно рассматривать как логические утверждения. Давайте рассмотрим следующее:

Кэти любит шоколад => Александр любит Кэти

Это можно прочитать как подтекст, который говорит: если Кэти любит шоколад, то Александр любит Кэти. Это также может быть истолковано как то, что Кэти любит шоколад подразумевает, что Александр любит Кэти.

Аналогично, давайте рассмотрим следующее правило:

Криминальные фильмы, английский язык => Martin Scorsese

Это может быть прочитано следующим образом: Если вам нравятся криминальные фильмы на английском языке, то вам понравятся фильмы, снятые Мартином Скорсезе.

Эта конструкция используется в различных формах в логическом программировании для решения различных типов задач. Давайте продолжим и посмотрим, как решить эти проблемы в Python.

Установка пакетов Python

Прежде чем мы начнем логическое программирование на Python, нам нужно установить пару пакетов. Пакет logpy — это пакет Python, который делает доступным логическое программирование на Python.

Мы также будем использовать sympy для решения некоторых проблем. Итак, давайте установим logpy и sympy с помощью pip :

$ pip3 install logpy $ pip3 install sympy

Согласование математических выражений

Мы постоянно сталкиваемся с математическими операциями. Логическое программирование — это очень эффективный способ сравнения выражений и обнаружения неизвестных значений. Давайте посмотрим, как это сделать.

Создайте новый файл Python и импортируйте следующие пакеты:

from logpy import run, var, fact import logpy.assoccomm as la

Определите пару математических операций:

add = 'addition' mul = 'multiplication'

И сложение, и умножение являются коммутативными операциями. Давайте определим их, а именно:

fact(la.commutative, mul) fact(la.commutative, add) fact(la.associative, mul) fact(la.associative, add)

Давайте определим некоторые переменные:

Рассмотрим следующее выражение:

expression_orig = 3 x (-2) + (1 + 2 x 3) x (-1)

Сгенерируем это выражение с замаскированными переменными.

expression1 = (1 + 2 x a) x b + 3 x c
expression2 = c x 3 + b x (2 x a + 1)
expression3 = (((2 x a) x b) + b) + 3 x

Если вы достаточно внимательны, вы заметите, что все три выражения представляют одно и то же основное выражение.

Наша цель — сопоставить эти выражения с исходным выражением для извлечения неизвестных значений:

expression_orig = (add, (mul, 3, -2), (mul, (add, 1, (mul, 2, 3)), -1)) expression1 = (add, (mul, (add, 1, (mul, 2, a)), b), (mul, 3, c)) expression2 = (add, (mul, c, 3), (mul, b, (add, (mul, 2, a), 1))) expression3 = (add, (add, (mul, (mul, 2, a), b), b), (mul, 3, c))

Сравните выражения с исходным выражением. Данный метод обычно используется в logpy . Этот метод принимает входные аргументы и выполняет выражение.

Первый аргумент — это число значений, второй аргумент — это переменная, а третий аргумент — это функция:

print(run(0, (a, b, c), la.eq_assoccomm(expression1, expression_orig))) print(run(0, (a, b, c), la.eq_assoccomm(expression2, expression_orig))) print(run(0, (a, b, c), la.eq_assoccomm(expression3, expression_orig)))

Полный код предоставлен в expression_matcher.py . Если вы запустите код, вы увидите следующий вывод в своем терминале:

Три значения в первых двух строках представляют собой значения для a, b и c. Первые два выражения совпадают с исходным выражением, а третье ничего не возвращает.

Причина в том, что хоть третье выражение математически одинаково, оно структурно отличается. Сравнение шаблонов работает путем сравнения структуры выражений.

Источник

Читайте также:  Программирование esp 01 через usb
Оцените статью