Как использовать tuple_in из clpfd?

Я слежу за упражнениями clpfd здесь: http://www.pathwayslms.com/swipltuts/clpfd/clpfd.html

У меня есть следующее решение, например 5 номер 1

trains([[1,2,0,1], % from station, to station, departs at, arrives at
       [2,3,4,5],
       [2,3,0,1],
       [3,4,5,6],
       [3,4,2,3],
       [3,4,8,9]]).

threepath(A, D, Ps) :-
    Ps = [[A,B,_T0,T1],[B,C,T2,T3],[C,D,T4,_T5]],
    T2 #> T1,
    T4 #> T3,
    trains(Ts),
    tuples_in(Ps, Ts).


allpaths(From,To,Route):-
  trains(Ts),
  length(Ts,Max_Trains),
  between(2,Max_Trains,Length_Of_Route),
  Route=[_,_|_],length(Route,Length_Of_Route),
  maplist(same_length([_,_,_,_]),Route),
  create_chain(Route,TimeChain,1),
  train_chain(Route),
  chain(TimeChain, #<),
  tuples_in(Route,Ts),
  nth1(1,Route,[From|_]),
  nth1(Length_Of_Route,Route,[_,To|_]).

create_chain([],[],_).
create_chain(List_of_Lists,[First,Second|Chain],1):-
  List_of_Lists =[Item|T],
  Item =[_T1,_T2,First,Second],
  create_chain(T,Chain,2).
create_chain(List_of_Lists,[First,Second|Chain],2):-
  List_of_Lists =[Item|T],
  Item =[_T1,_T2,First,Second],
  create_chain(T,Chain,1).

train_chain([_]).
train_chain(List_Of_Lists):-
  List_Of_Lists =[First,Second|T],
  First = [_One,Two,_,_],
  Second =[Two,_Three,_,_],
  train_chain([Second|T]).

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

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

employees([
 [1, 75, 0, 30, 25],
 [2, 83, 0, 45, 25],
 [3, 90, 1, 45, 50],
 [4, 45, 3, 75, 25],
 [5, 89, 0, 52, 50]
 ]).

promotions(Es,Promotions):-
  employees(Es),
  findall([Id,Score,V,T,RT],
    (member([Id,Score,V,T,RT],Es),Score>80,V=<1,T>RT),
  Promotions).

person user27815    schedule 18.09.2015    source источник


Ответы (2)


Я думаю, должно быть так просто, как

ex2(EmployeeId) :-
 employees(Es),
 tuples_in([[EmployeeId, LastReviewScore, NumOfSafetyViolations, TimeInGrade, RequiredTimeForPromotion]], Es),
 LastReviewScore #> 80, NumOfSafetyViolations #=< 1, TimeInGrade #> RequiredTimeForPromotion,
 label([EmployeeId]).

Преимущество состоит в том, что отношение между значениями, которые используются для идентификации кандидатов, можно оставить неопределенным, пока о проблеме не станет известно что-нибудь интересное.

Простой пример не показывает таких преимуществ ... Я нашел tuple_in полезным для решения кроссвордов, где он позволяет резко сократить время решения.

person CapelliC    schedule 18.09.2015

Я рад, что наконец-то смог ответить на что-то на StackOverflow. Вот мое решение первого вопроса. Я использую шаблон Accumulator, который вы можете найти в главе 6 LearnPrologNow, здесь также есть удобные слайды, просто перейдите к главе 6: слайды < / а>

Сначала я вызываю вспомогательный предикат, который перегружает одно и то же имя, но с 4 аргументами, третий - это время, в которое я пришел From. Для инициализации это число -1.

findpath(From, To, Path) :- findpath(From, To, -1, Path).

Затем я делаю рекурсию на findpath / 4,

% base case: from X1 to Xn there is direct train
findpath(X1, Xn, Time, [[X1, Xn, T0, T1]]) :- 
            trains(Ts),
            T0 #> Time,
            tuples_in([[X1, Xn, T0, T1]], Ts).

% go to a midpoint X2, leave X2 -> Xn to recursion
findpath(X1, Xn, Time, [P|Ps]) :-
            trains(Ts),
            P = [X1, X2, T0, T1],
            T0 #> Time, 
            tuples_in([P], Ts),
            findpath(X2, Xn, T1, Ps).

Но то же самое и с вами, я не уверен, что это наилучшим образом использует clpfd. Я называю tuples_in/2 для каждого элемента Ps и сомневаюсь, что это больше, чем необходимо.

person CraggySillica    schedule 25.05.2020