You could have a look at the potassco suite[0]. It is a grounder and solver for Answer Set Programming (ASP). ASP is a form of Logic Programming.
% Each shift needs a nurse).
1 { shift_nurse(Shift, Nurse): nurse(Nurse) } 1 :- shift(shift).
% It cannot be that a nurse does two shifts in a row.
:- nurse(Nurse), shift_nurse(Shift1,Nurse),shift_nurse(Shift2,Nurse), Shift1 + 1 = Shift2.
[0] https://potassco.org/doc/start/Found the original comment: https://news.ycombinator.com/item?id=41756679
Would this still work with ASP?