Сокращение логического выражения

У меня есть выражение, предположим,

a = 1 && (b = 1 || b != 0 ) && (c >= 35 || d != 5) && (c >= 38 || d = 6)

Я ожидаю, что он будет сокращен до

a = 1 && b != 0 && (c >= 38 || d = 6)

Есть ли у кого-нибудь предложения? Указатели на какой-либо алгоритм?

Nota Bene: Карта Карно или Куайн-МакКласки здесь не подходят, как мне кажется. Поскольку эти методы не обрабатывают серые случаи. Я имею в виду, что выражение можно свести лишь к тому, что вещи похожи на А или А' или ничего, или, скажем, черное, белое или бесцветное. Но здесь у меня серые оттенки, как вы видите.

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


comment
Существуют ограничения на то, насколько сокращение может быть выполнено за полиномиальное время. Например, если бы вы всегда могли привести любое выражение в конъюнктивной нормальной форме к его простейшей форме, вы бы решили проблему открытого 3SAT.   -  person mbeckish    schedule 28.02.2012
comment
@mbeckish: это звучит пугающе для меня. На самом деле, я не знал об этих вещах, пока вы, ребята, не направили меня в правильном направлении. Я думал не только о 3SAT, но и о проблемах с nSAT. Теперь все это кажется невозможным.   -  person Adeel Ansari    schedule 29.02.2012
comment
Не бойтесь браться за NP-трудные задачи. Для большинства из них трудная часть будет находиться в относительно небольшой области проблемного пространства, в фазовом переходе между неразрешимыми и легкими задачами. Если бы решение NP-сложных задач всегда было невозможно, я бы остался без работы. Многое зависит от того, насколько далеко вы ожидаете масштабирования вашего алгоритма.   -  person twinterer    schedule 29.02.2012


Ответы (2)


Я думаю, вы сможете добиться желаемого, используя правила обработки ограничений. Вам нужно будет написать правила, упрощающие выражения ИЛИ и И.

Основная трудность будет заключаться в проверке следования ограничений, которая говорит вам, какие части вы можете отбросить. Например, (c >= 35 || d != 5) && (c >= 38 || d = 6) упрощается до (c >= 38 || d = 6), поскольку первое следует из второго, т. е. последний более конкретен. Однако для выражений ИЛИ вам нужно будет выбрать более общую часть.

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

person twinterer    schedule 28.02.2012
comment
После краткого прочтения о программировании с ограничениями, затем о логическом программировании с ограничениями (mgibsonbr указал в другом посте), затем о проблемах удовлетворения ограничений, затем о правилах обработки ограничений, а затем об оптимизации ограничений, я считаю, что моя проблема заключается в оптимизации ограничений, и я также считаю, что любой алгоритм обратного отслеживания был бы полезен. Я особенно изучаю B & B и Bucket Elimination, где последний не является алгоритмом возврата. Я иду в правильном направлении? - person Adeel Ansari; 01.03.2012
comment
@AdeelAnsari: Да, вы можете рассматривать это как своего рода проблему оптимизации, если вы принимаете количество предложений в качестве меры и хотите найти кратчайшее представление. Обычно B&B является хорошим выбором при решении задач COP, но он поможет только в том случае, если вы можете вычислить некоторую нижнюю границу количества предложений в конечном результате, в противном случае это полный поиск. Возврат будет включен при использовании CLP. CHR предназначен для фиксированного выбора, то есть без возврата, но реализации CHR поверх CLP фактически имеют возврат (например, в ECLiPSe). Помогает ли устранение ведра, я не знаю. - person twinterer; 01.03.2012
comment
@AdeelAnsari: кстати, вы ищете полностью универсальное решение или работаете над решением для конкретного варианта использования? Если второе, то сколько переменных и с каким размером домена вам придется иметь дело? - person twinterer; 01.03.2012
comment
Возьмите его как if-clause в программной функции или where-clause в операторе sql-select. Я пытаюсь уменьшить ограничения, если одни влекут за собой другие, в этом состоянии. Я не думаю, что смогу исправить размер переменных. - person Adeel Ansari; 02.03.2012

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

Общий принцип прост: несвязанная переменная может иметь любое значение; когда вы проверяете его на неравенства, его набор возможных значений ограничен одним или несколькими интервалами. Когда/если эти интервалы сходятся в одной точке, эта переменная привязывается к этому значению. Если, OTOH, любое из этих неравенств считается неразрешимым для каждого значения в интервалах, возникает логическая ошибка [программирования].

См. также это для примера того, как это делается на практике с помощью swi- пролог. Надеюсь, вы найдете ссылки или ссылки на базовые алгоритмы, чтобы вы могли воспроизвести их на выбранной вами платформе (возможно, даже найти готовые библиотеки).

Обновление: я попытался воспроизвести ваш пример, используя swi-prolog и clpfd, но не получил ожидаемых результатов, только близкие. Вот мой код:

?- [library(clpfd)].
simplify(A,B,C,D) :-
    A #= 1 ,
    (B #= 1 ; B #\= 0 ) ,
    (C #>= 35 ; D #\= 5) ,
    (C #>= 38 ; D #= 6).

И мои результаты при возврате (разрывы строк вставлены для удобочитаемости):

10 ?- simplify(A,B,C,D).

A = 1,
B = 1,
C in 38..sup ;

A = 1,
B = 1,
D = 6,
C in 35..sup ;

A = 1,
B = 1,
C in 38..sup,
D in inf..4\/6..sup ;

A = 1,
B = 1,
D = 6 ;

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup,
C in 35..sup ;

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup,
D in inf..4\/6..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup.

11 ?- 

Итак, программа выдала 8 результатов, среди тех 2, которые вас интересовали (5-й и 8-й):

A = 1,
B in inf.. -1\/1..sup,
C in 38..sup ;

A = 1,
D = 6,
B in inf.. -1\/1..sup.

Другие были излишними, и, возможно, их можно было бы устранить с помощью простых автоматических логических правил:

1st or 5th ==> 5th          [B == 1  or B != 0 --> B != 0]
2nd or 4th ==> 4th          [C >= 35 or True   --> True  ]
3rd or 1st ==> 1st ==> 5th  [D != 5  or True   --> True  ]
4th or 8th ==> 8th          [B == 1  or B != 0 --> B != 0]
6th or 8th ==> 8th          [C >= 35 or True   --> True  ]
7th or 3rd ==> 3rd ==> 5th  [B == 1  or B != 0 --> B != 0]

Я знаю, что это далеко не общее решение, но, как я уже сказал, надеюсь, это только начало...

P.S. Я использовал «обычные» И и ИЛИ (, и ;), потому что clpfd (#/\ и #\/) дали очень странный результат, который я сам не мог понять... может быть, кто-то более опытный может пролить свет на это...

person mgibsonbr    schedule 28.02.2012
comment
Спасибо, приятель. Это очень хорошо, что вы. Я смотрю на это и пытаюсь переварить. - person Adeel Ansari; 28.02.2012