1

Adding the following rule to my code results in an error message (info: operation undefined (Max-Min)):

rank_difference(Room, Deck, Diff) :-
    played(Room, Deck),
    Min = #min {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    Max = #max {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    Diff = Max - Min.

played(Room, Deck) implies that there exists at least one seat(Player, Room, Deck) predicate (in fact that there exist exactly 3 or 4) while rank(Player, Rank) exists for each player so this isn't supposed to be an empty set issue.

Update - Runnable example (without any of the constraints):

#const nRounds = 4.
#const nPlayers = 13.
#const nRooms = 4.
#const nDecks = 10.

player(1..nPlayers).
room(1..nRooms).
deck(1..nDecks).
writer(1,1;2,2;3,3;4,4).
rank(Player, Player) :- player(Player).

nRounds { round(Player, 1..nDecks) } nRounds :- player(Player).
{ played(Room, Deck) } :- room(Room), deck(Deck).
3 { seat(Player, Room, Deck) : round(Player, Deck) } 4 :- played(Room, Deck).

rank_difference(Room, Deck, Diff) :-
    played(Room, Deck),
    Min = #min {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    Max = #max {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    Diff = Max - Min.
Max Ostrowski
  • 575
  • 1
  • 3
  • 15
rudolfovic
  • 3,163
  • 2
  • 14
  • 38
  • Your encoding looks correct, can you create a sample instance where I can reproduce the error? – NTP May 18 '21 at 16:31

1 Answers1

2

The grounder can not infer that the set inside your min/max aggregate isn't actually empty. Therefore valid solutions (at least during grounding) are also #sup for #min and #inf for #max. https://en.wikipedia.org/wiki/Infimum_and_supremum Doing arithmetic with these values is undefined. You have to explicitly bound the result of the operation so in this case:

rank_difference(Room, Deck, Diff) :-
    played(Room, Deck),
    Min = #min {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    Max = #max {Rank: seat(Player, Room, Deck), rank(Player, Rank)},
    rank(_, Min), rank(_, Max),
    Diff = Max - Min.
Max Ostrowski
  • 575
  • 1
  • 3
  • 15
rudolfovic
  • 3,163
  • 2
  • 14
  • 38