Я считаю, что такие вещи регулярно выполняются в программировании логики ограничений. К сожалению, у меня недостаточно опыта в этом, чтобы дать более точные детали, но это должно быть хорошей отправной точкой.
Общий принцип прост: несвязанная переменная может иметь любое значение; когда вы проверяете его на неравенства, его набор возможных значений ограничен одним или несколькими интервалами. Когда/если эти интервалы сходятся в одной точке, эта переменная привязывается к этому значению. Если, 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