not(A(X)) работает следующим образом: если prolog не может доказать верность A(X), то not(A(X)) считается истинным, в противном случае — ложным. Это поведение отличается от классического инвертирования булевой переменной, поэтому not в логическом программировании получил название «negation as failure».
In Planner, negation as failure could be implemented as follows:
if (not (goal p)), then (assert ¬p)
which says that if an exhaustive search to prove p fails, then assert ¬p.[1] Note that the above example uses true mathematical negation, which cannot be expressed in Prolog.
что переводится как
Negation as failure (то есть not) может быть написан на Planner-е так: if (not (goal p)), then (assert ¬p), что означает: если не удалось доказать истинность p, тогда говорим что отрицание от p истинно (под отрицанием здесь понимается инвертирование булевой переменной). Обратите внимание, что описанный выше пример использует классическое математическое отрицание (то есть инвертирование булевой переменной), которое невозможно описать на прологе.
То есть тут описывается как работает в Prolog-е not и говорится, что это не тоже самое, что и инвертирование булевой переменной, что вполне логично: в Prolog-е нет присвоения переменных, следовательно нет и инвертирования переменных.
The logical status of negation as failure was unresolved until Keith Clark [1978] showed that, under certain natural conditions, it is a correct (and sometimes complete) implementation of classical negation with respect to the completion of the program.
что переводится как
Статус negation as failure (то есть not) был непонятен до тех пор, пока Кейф Кларк в 1978 не доказал, что not это правильная реализация классического отрицания.
Таким образом, в приведенном вами источнике сказано, что not — это логическое отрицание.
По поводу примера, который вы привели: уверен, что Prolog скажет, что A истинно. Prolog не сможет доказать истинность B (т.к. не описано правило по которому оно истинно), следовательно not(B) истинно, из чего следует истинность A согласно правилу 1. Могу написать код, если у вас остались сомнения.
Синтаксис пролога запрещает использовать оператор отрицания следующим образом: not(b(X)) :- <Условие>. Однако ничего не мешает определить новый предикат notB(X) и сказать, что одновременная истинность b(X) и notB(X) приводит к противоречию.
Пример 1
1)Если А ложно, то B ложно
2)А истинно относительно человека с именем «Johnson»
3)B истинно относительно «Smith»
aOutput(X) :- man(X), not(a(X)), conflict(X). %A истинно, если ложность A приводит к противоречию
aOutput(X) :- a(X).
/*Дробление A на a и aOutput возникло из-за проблем с зацикливанием, о которых я уже писал.
Далее, если нужно указать почему A истинно, то следует использовать a, во всех остальных случаях — aOutput*/
aOutput(X) :- man(X), not(a(X)), conflict(X). %A истинно, если ложность A приводит к противоречию
aOutput(X) :- a(X).
/*Дробление A на a и aOutput возникло из-за проблем с зацикливанием, о которых я уже писал.
Далее, если нужно указать почему A истинно, то следует использовать a, во всех остальных случаях — aOutput*/
Почитал дискуссию, судя по всему у вас не получилось описать правило «если А истинно, то Б ложно», поэтому вы утверждаете, что в Прологе отсутствует логическое отрицание. Я правильно вас понял?
Приведенный пример означает: dontAttack истина, если не истина attack. Поскольку это единственное правило, описывающее dontAttack с данным набором параметров, то во всех остальных случаях (если attack выполняется), правило dontAttack не выполняется (ложно). Это поведение соответствует оператору отрицания, так как true переходит в false, а false в true.
Не могли бы вы пожалуйста указать источник, в котором это сказано?
Гугл считает иначе, выводя первой ссылкой описание оператора отрицания, да и в статье есть пример его использования:
dontAttack(X1, Y1, X2, Y2) :-
any(X1), any(Y1), any(X2), any(Y2), not(attack(X1, Y1, X2, Y2)).
есть ли комерческий/промышленный софт написанный на прологе?
Цитата из книги Эрика Эванса Предметно-ориентированное проектирование
Еще один перспективный подход в декларативной архитектуре — это логическое программирование (rule-based programming) с механизмом выводов и базой правил. К сожалению, и эта идея может провалиться из-за некоторых тонкостей. Хотя программа, основанная на совокупности логических правил, в принципе декларативна, в большинстве таких систем имеются «управляющие предикаты», добавленные туда для возможности настройки производительности. Этот управляющий код вносит побочные эффекты, и в результате поведение программы уже не полностью определяется декларированными правилами. Добавление, удаление и переупорядочение правил может привести к непредсказуемым и неправильным результатам. Поэтому программист в логической парадигме, как и программист объектно-ориентированный, должен тщательно следить за очевидностью и предсказуемостью поведения кода.
Похоже, Эрик Эванс знал промышленные проекты, в которых использовалась логическая парадигма, так как книга посвящена проектированию программ, работающих со сложной предметной областью.
Ну, это только с первого взгляда так кажется.В Prolog-е нет таких понятий, как присвоение переменных и вызов функций. Всё описывается в виде отношений между сущностями и безусловных фактов о сущностях. Например, A = stdio::read() концептуально означает «существует A, совпадающая с тем что ввёл пользователь в консоль», это не присвоение переменной. Точно также, operation(X1, X2, "+", Result) :- Result = X1 + X2 — это не вызов функции и не присвоение Result суммы X1 + X2. Почитайте статью (я уверен, что вы её не читали), там в первом примере есть описание отношения формулы и операций, с первого взгляда может показаться, что это обычный вызов функции, в котором операторы разделяются запятыми, но по ходу разбора примера становится очевидно, что это не так.
Prolog не вводит в заблуждение. Если необходимо доказать гипотезу, то пролог либо выведет её доказательство, либо скажет что не смог его найти (и тогда Prolog-у нужно будет добавить входных фактов). Если нужно опровергнуть гипотезу, то просто немного по-другому задаётся главный вопрос. Ошибиться можно, только если истолковать ответ Prolog-а «я не смог найти доказательство» как «гипотеза не верна», но тут программист сам себе злой чебурашка, и дело совсем не в языке.
Ну, бороться с зацикливаниями на уровне языка как раз таки можно — при каждом вызове функции (обходе факта или предиката) проверяем нет ли зацикливания -> если есть кидаем исключение -> перехватываем там где зацикливание началось -> перебираем факты дальше не заходя в зацикливающую ветвь. Если бы были под рукой исходники компилятора, быстро бы решил проблему. В остальном претензий к языку нет.
из википедии: Логи́ческое программи́рование — парадигма программирования, основанная на автоматическом доказательстве теорем.
Есть опыт автоматического доказательства простеньких теорем на прологе, могу написать на хабре статью на эту тему, если кому интересно.
в глазах команды этот шаг может выглядеть как выбор жертвы
Манагер информирует команду о решении начальства. Кроме того, предлагает свою помощь — если кто хочет уволиться сейчас то надавлю на нужных людей и прослежу чтобы трудовую не замарали, а потом такой возможности может и не быть. В глазах команды манагера не за что упрекнуть.
в его глазах вы или сплоховали или нужно обставить этот шаг
Можно сказать: «Я не мог скрывать от команды положение вещей. Мы с тобой это обговорили когда я выбивал кадры. Неужели ты не предвидел ОЧЕВИДНЫЕ последствия СВОЕГО решения?»
не ушли действительно ценные сотрудники
По условию кейса в команде одни середняки.
Пока она будет формироваться, неизбежен провал в производительности. А это дополнительные риски.
Согласен, это риск. Но когда человек ищет новую работу, он неэффективен, может оставить после себя кучу багов, которые потом сложно будет исправить. Это гораздо больший риск. Имхо, лучше чтобы те кто хочет уйти заявили об этом как можно раньше. Когда провоцируем их на это, имеем возможность оценить, кто хочет уйти больше. Просто попросить людей сообщить о их намерениях — значит надеяться на удачу. Если человек не видит с вами общего будущего, то нет и сильных причин быть с вами полностью откровенными.
А чем это плохо? Напомню, что ушли самые не лояльные. В команде не было звёзд. Их бы всё равно уволить пришлось, иначе бы сложилось впечатление что компания не держит слова. На вариант, что «повезёт» и не придётся, надежды мало. Почему тогда уж вы не рассматриваете шанс, что «повезёт», и никто не уволится, но приложит усилия чтобы вытащить проект? Лучше пусть хоть сами уволятся, так хоть имидж компании не сильно пострадает в глазах работников.
допустили переход команды из стадии производства в стадию формирования
А чем это плохо? Команда то всё равно не справлялась. И команда не «кристализованная», раз ультиматум «уйдём все» не предъявили. Да и решение «уволить половину» не было принято именно манагером, он в данном случае просто взял под контроль этот процесс.
Планировать необходимо, но также важна и импровизация. Автор книги «Программист-фанатик» утверждает, что в критических ситуациях наиболее важна именно импровизация (но она невозможна без хорошей квалификации). Какие в данной ситуации мне видятся проблемы — 1)заказчик теряет деньги, 2)если программисты лишатся работы то они возможно будут недовольны, 3)если манагер не разрулит ситуацию или не докажет что она неразруливаема при текущих ресурсах то понизится его авторитет. При этом непонятно, какую из этих проблем можно решить и как. Заранее неизвестно, можно ли как-то убрать зависимость между потерей заказчиком денег и сроком релиза, можно ли убедить программиста что увольнение это не плохо а хорошо и т.д. Не узнаешь, пока не попробуешь. Когда известен результат попыток, возможно придётся изменить план на 180 градусов. Может быть для решения проблемы и не нужно биться над тем, чтобы выкладывать релиз в срок. А может быть нужно биться как раз над этим. Как составить хороший план в условиях такой неопределенности? Да, нужно составить первоначальный план, но он может измениться после наступления первого же события. При этом если команде заранее сказать — мешайте чай по часовой стрелке, и будет вам счастье, то после этого сложно будет направить их в другую сторону. Как они отнесутся к тому, когда после ваших заверений что мешание чая по часовой стрелке гарантирует успех, на следующий день вы заявите: «я передумал, уволен ты, ты и ты!».
Вы рассуждаете с точки зрения работника, а не манагера и отвечаете на вопрос — какое развитие событий благоприятно для зоны комфорта работника, чтобы ему было на что валить вину когда сроки выкладки снова запаздают (а так скорее всего и будет). Давайте повнимательнее посмотрим на ваше предложение с точки зрения работника: зарплата та же, не уважают, а заставляют лезть из кожи вон ради плана, с которым работник может быть и не согласен (всем не угодишь). Работник то честно работает, а тут какие-то неприятности потому что его команда видите ли плохо работает (может дело и в нём, но он никогда себе не признается). Будет он эффективнее и более мотивирован из-за наличия плана? Вряд ли. Повышение мотивации работников как средство решения проблемы посредством плана скорее всего не сработает. А если плана нету, может хоть сами что дельное предложат. По крайней мере слова о том, что у вас есть план который поможет решить проблему, когда его у вас его нет — это такая же ложь, что и «никого не уволят». Ну, может быть, уличить вас будет чуть сложнее
Если в команде есть человек, способный сформировать план, то где он был во время предыдущих фэйлов? Если никто не видит закономерности в фэйлах, то никто не понимает их причину (например, 1)проблемы в коде или 2)отсутствие единого видения бизнесс-процессов заказчика и целей программы среди команды, из-за чего код вроде бы корректен, но противоречив или 3)жадность заказчика который хочет за итерацию больше фич чем может выкатить команда или ещё что угодно).
Ну ок, кто-то умный скажет, давайте писать n тестов, ревьюить код m раз и не уходить из офиса пока не выполним столько-то работ. А причина в жадности заказчика. Ну будете вы следовать плану, и как вам это поможет? Вспоминается поговорка — когда тысяча человек умирает по плану, то это нормально, когда внезапно умирает сто человек — то это трагедия. В данном случае план без понимания ситуации не гарантирует, что сроки будут выполнены.
Какое решение пришло мне в голову — 1.У начальства узнаём кого смогут выделить на замену, если кто то решит сбежать посреди итерации. Выбиваем как можно лучших спецов. 2.На собрании объявляем, что в случае срыва сроков половину уволят, и с какой формулировкой в трудовой — неизвестно. Но если кто-то проявит желание уволиться сразу, то договорюсь чтобы уволили по-нормальному, потом мол ничего сделать уже не смогу. 3.Увольняем тех кто пришёл первым (самых немотивированных и нервных), идём к начальству и говорим дескать пара человек уволилась, давайте отменим решение (пока все не разбежались, тем более что показательная кровь пролита) и немного отодвинем срок следующего релиза. 4.Независимо от того отменили или нет решение идём и говорим команде что вроде как начальство смягчилось и возможно репрессий не будет. 5.Пришедших новых (наверное где то троих) сотрудников просим свежим взглядом посмотреть на проект и оценить что не так. Мотивируем плюшками, премиями и рассказами о важности проекта новичков работать по выходным, дабы они воплощали свои идеи и предложения, которые у них возникли. Главное чтобы они не переусердствовали, улучшения ради улучшений — не выход. Возможно иногда мельком консультироваться с каким нибудь опытным архитектором (в компании на 100 человек хоть одна светлая голова должна быть), проверяя пользу от предложений. Старых сотрудников не заставляем работать сверхурочно и не перенапрягаем их — велик риск что они где-нибудь ошибутся, они итак морально истощены.
Если сроки не срываются, всё ок.
Когда сроки срываются, достаём красивую отмазку, что новички ещё не втянулись в проект и просим ещё шанс, давим на то что заказчик сам инициировал увольнение части команды, он дескать умный и должен был предвидеть последствия.
Если команда сообща договаривается увольняться одновременно и все сразу, прёмся к начальству и говорим что вон какая дружная и сыгранная Команда, нельзя таких людей разбивать, давайте отменим решение.
Интересно было бы узнать, какие недостатки у этого решения?
Нашёл по приведённой вами ссылке следующий текст:
что переводится как
То есть тут описывается как работает в Prolog-е not и говорится, что это не тоже самое, что и инвертирование булевой переменной, что вполне логично: в Prolog-е нет присвоения переменных, следовательно нет и инвертирования переменных.
Далее говорится следующее:
что переводится как
Таким образом, в приведенном вами источнике сказано, что not — это логическое отрицание.
По поводу примера, который вы привели: уверен, что Prolog скажет, что A истинно. Prolog не сможет доказать истинность B (т.к. не описано правило по которому оно истинно), следовательно not(B) истинно, из чего следует истинность A согласно правилу 1. Могу написать код, если у вас остались сомнения.
Пример 1
1)Если А ложно, то B ложно
2)А истинно относительно человека с именем «Johnson»
3)B истинно относительно «Smith»
open core
class predicates
man:(string) nondeterm anyflow.
aOutput:(string) nondeterm anyflow.
a: (string) nondeterm anyflow.
b:(string) nondeterm(i) nondeterm(o).
notB:(string) nondeterm(i) nondeterm(o).
notBOutput:(string) nondeterm(i) nondeterm(o).
conflict:(string) nondeterm anyflow.
conflictOutput:(string) nondeterm anyflow.
question:() procedure.
clauses
man(«Smith»).
man(«Lucas»).
man(«Johnson»).
a(«Johnson»).
notB(X) :- man(X), not(a(X)).
notBOutput(X) :- man(X), not(aOutput(X)).
conflict(X) :- b(X), notB(X).
aOutput(X) :- man(X), not(a(X)), conflict(X). %A истинно, если ложность A приводит к противоречию
aOutput(X) :- a(X).
/*Дробление A на a и aOutput возникло из-за проблем с зацикливанием, о которых я уже писал.
Далее, если нужно указать почему A истинно, то следует использовать a, во всех остальных случаях — aOutput*/
conflictOutput(X) :- b(X), notBOutput(X).
b(«Smith»).
question() :-
aOutput(X),
not(conflictOutput(X)),
stdio::write(«A true for », X),
stdio::nl,
fail.
question().
run() :- question(), stdio::write(«End»), _ = stdio::readChar().
end implement main
goal
console::runUtf8(main::run).
Вывод программы:
A true for Smith
A true for Johnson
Пример 2
1)Если А истинно, то B ложно
2)А истинно относительно «Johnson»
3)А истинно относительно «Smith»
4)B истинно относительно «Smith»
open core
class predicates
man:(string) nondeterm anyflow.
aOutput:(string) nondeterm anyflow.
a: (string) nondeterm anyflow.
b:(string) nondeterm(i) nondeterm(o).
notB:(string) nondeterm(i) nondeterm(o).
notBOutput:(string) nondeterm(i) nondeterm(o).
conflict:(string) nondeterm anyflow.
conflictOutput:(string) nondeterm anyflow.
question:() procedure.
clauses
man(«Smith»).
man(«Lucas»).
man(«Johnson»).
a(«Johnson»).
a(«Smith»).
notB(X) :- a(X).
notBOutput(X) :- aOutput(X).
conflict(X) :- b(X), notB(X).
aOutput(X) :- man(X), not(a(X)), conflict(X). %A истинно, если ложность A приводит к противоречию
aOutput(X) :- a(X).
/*Дробление A на a и aOutput возникло из-за проблем с зацикливанием, о которых я уже писал.
Далее, если нужно указать почему A истинно, то следует использовать a, во всех остальных случаях — aOutput*/
conflictOutput(X) :- b(X), notBOutput(X).
b(«Smith»).
question() :-
aOutput(X),
not(conflictOutput(X)),
stdio::write(«A true for », X),
stdio::nl,
fail.
question().
run() :- question(), stdio::write(«End»), _ = stdio::readChar().
end implement main
goal
console::runUtf8(main::run).
Вывод программы:
Только «A true for Johnson», потому что истинность A для «Smith» приводит к противоречию.
Имхо, если у вас когда-то что-то не получилось, то это не повод заявлять, что это принципиально невозможно и вводить людей в заблуждение.
Приведенный пример означает: dontAttack истина, если не истина attack. Поскольку это единственное правило, описывающее dontAttack с данным набором параметров, то во всех остальных случаях (если attack выполняется), правило dontAttack не выполняется (ложно). Это поведение соответствует оператору отрицания, так как true переходит в false, а false в true.
Не могли бы вы пожалуйста указать источник, в котором это сказано?
Гугл считает иначе, выводя первой ссылкой описание оператора отрицания, да и в статье есть пример его использования:
dontAttack(X1, Y1, X2, Y2) :-
any(X1), any(Y1), any(X2), any(Y2), not(attack(X1, Y1, X2, Y2)).
Похоже, Эрик Эванс знал промышленные проекты, в которых использовалась логическая парадигма, так как книга посвящена проектированию программ, работающих со сложной предметной областью.
Есть опыт автоматического доказательства простеньких теорем на прологе, могу написать на хабре статью на эту тему, если кому интересно.
Манагер информирует команду о решении начальства. Кроме того, предлагает свою помощь — если кто хочет уволиться сейчас то надавлю на нужных людей и прослежу чтобы трудовую не замарали, а потом такой возможности может и не быть. В глазах команды манагера не за что упрекнуть.
Можно сказать: «Я не мог скрывать от команды положение вещей. Мы с тобой это обговорили когда я выбивал кадры. Неужели ты не предвидел ОЧЕВИДНЫЕ последствия СВОЕГО решения?»
По условию кейса в команде одни середняки.
Согласен, это риск. Но когда человек ищет новую работу, он неэффективен, может оставить после себя кучу багов, которые потом сложно будет исправить. Это гораздо больший риск. Имхо, лучше чтобы те кто хочет уйти заявили об этом как можно раньше. Когда провоцируем их на это, имеем возможность оценить, кто хочет уйти больше. Просто попросить людей сообщить о их намерениях — значит надеяться на удачу. Если человек не видит с вами общего будущего, то нет и сильных причин быть с вами полностью откровенными.
А чем это плохо? Напомню, что ушли самые не лояльные. В команде не было звёзд. Их бы всё равно уволить пришлось, иначе бы сложилось впечатление что компания не держит слова. На вариант, что «повезёт» и не придётся, надежды мало. Почему тогда уж вы не рассматриваете шанс, что «повезёт», и никто не уволится, но приложит усилия чтобы вытащить проект? Лучше пусть хоть сами уволятся, так хоть имидж компании не сильно пострадает в глазах работников.
А чем это плохо? Команда то всё равно не справлялась. И команда не «кристализованная», раз ультиматум «уйдём все» не предъявили. Да и решение «уволить половину» не было принято именно манагером, он в данном случае просто взял под контроль этот процесс.
Вы рассуждаете с точки зрения работника, а не манагера и отвечаете на вопрос — какое развитие событий благоприятно для зоны комфорта работника, чтобы ему было на что валить вину когда сроки выкладки снова запаздают (а так скорее всего и будет). Давайте повнимательнее посмотрим на ваше предложение с точки зрения работника: зарплата та же, не уважают, а заставляют лезть из кожи вон ради плана, с которым работник может быть и не согласен (всем не угодишь). Работник то честно работает, а тут какие-то неприятности потому что его команда видите ли плохо работает (может дело и в нём, но он никогда себе не признается). Будет он эффективнее и более мотивирован из-за наличия плана? Вряд ли. Повышение мотивации работников как средство решения проблемы посредством плана скорее всего не сработает. А если плана нету, может хоть сами что дельное предложат. По крайней мере слова о том, что у вас есть план который поможет решить проблему, когда его у вас его нет — это такая же ложь, что и «никого не уволят». Ну, может быть, уличить вас будет чуть сложнее
Ну ок, кто-то умный скажет, давайте писать n тестов, ревьюить код m раз и не уходить из офиса пока не выполним столько-то работ. А причина в жадности заказчика. Ну будете вы следовать плану, и как вам это поможет? Вспоминается поговорка — когда тысяча человек умирает по плану, то это нормально, когда внезапно умирает сто человек — то это трагедия. В данном случае план без понимания ситуации не гарантирует, что сроки будут выполнены.
Если сроки не срываются, всё ок.
Когда сроки срываются, достаём красивую отмазку, что новички ещё не втянулись в проект и просим ещё шанс, давим на то что заказчик сам инициировал увольнение части команды, он дескать умный и должен был предвидеть последствия.
Если команда сообща договаривается увольняться одновременно и все сразу, прёмся к начальству и говорим что вон какая дружная и сыгранная Команда, нельзя таких людей разбивать, давайте отменим решение.
Интересно было бы узнать, какие недостатки у этого решения?