How can I define a married couple in Clingo? - answer-set-programming

I'm trying to create 5 marriages, given 5 women and 5 man and their preferences to each other.
homem(miguel).
homem(joao).
homem(pedro).
homem(marco).
homem(carlos).
mulher(maria).
mulher(paula).
mulher(carla).
mulher(cristina).
mulher(ana).
all the marriages are stable (it is unstable if 2 person outside the marriage prefer each other more than their spouses), and I have their preferences to each other by ranks:
pref(miguel,paula,5).
pref(miguel,ana,4).
pref(miguel,maria,3).
pref(miguel,carla,2).
pref(miguel,cristina,1).
pref(maria,carlos,5).
pref(maria,miguel,4).
pref(maria,marco,3).
pref(maria,joao,2).
pref(maria,pedro,1).
pref(joao,maria,5).
pref(joao,paula,4).
pref(joao,carla,3).
pref(joao,cristina,2).
pref(joao,ana,1).
pref(paula,marco,5).
pref(paula,carlos,4).
pref(paula,joao,3).
pref(paula,miguel,2).
pref(paula,pedro,1).
pref(pedro,paula,5).
pref(pedro,carla,4).
pref(pedro,ana,3).
pref(pedro,cristina,2).
pref(pedro,maria,1).
pref(carla,miguel,5).
pref(carla,marco,4).
pref(carla,joao,3).
pref(carla,pedro,2).
pref(carla,carlos,1).
pref(marco,maria,5).
pref(marco,carla,4).
pref(marco,paula,3).
pref(marco,cristina,2).
pref(marco,ana,1).
pref(cristina,pedro,5).
pref(cristina,joao,4).
pref(cristina,marco,3).
pref(cristina,miguel,2).
pref(cristina,carlos,1).
pref(carlos,ana,5).
pref(carlos,carla,4).
pref(carlos,paula,3).
pref(carlos,maria,2).
pref(carlos,cristina,1).
pref(ana,marco,5).
pref(ana,joao,4).
pref(ana,pedro,3).
pref(ana,carlos,2).
pref(ana,miguel,1).
casamento(1..5).
% every person belongs to one group only.
1{in(H,M): casamento(C)}1 :- homem(H), mulher(M).
:- homem(H1), mulher(M1), homem(H2), mulher(M2),
pref(H1,M2,P1),pref(H1,M1,P2), P1>P2,
pref(M2,H1,P3), pref(M2,H2,P4); P3>P4.
but this does not work and I don't know why.

Problem 1
The rule
1{in(H,M): casamento(C)}1 :- homem(H), mulher(M).
doesn't mean that "every person belongs to one group only", but that "every pair of man and woman belongs to exactly one marriage. This is equivalent to say that every man is married with every woman.
Instead, you should express the contrary: every marriage should "generate" exactly one pair of people:
1{in(H,M,C): homem(H), mulher(M)}1 :- casamento(C) .
But this doesn't prevent a men (or woman) to belong to two different marriages. So you shoul also add:
:- in(H,M1,C1), in(H,M2,C2), C1!=C2 .
:- in(H1,M,C1), in(H2,M,C2), C1!=C2 .
Problem 2
Moreover, in your constraint you're considering every pair of people (not every pair of married people!). So you should replace homem(H1), mulher(M1), homem(H2), mulher(M2) with in(H1,M1,C1), in(H2,M2,C2).
Fixed code
casamento(1..5) .
1{in(H,M,C): homem(H), mulher(M)}1 :- casamento(C) .
:- in(H,M1,C1), in(H,M2,C2), C1!=C2 .
:- in(H1,M,C1), in(H2,M,C2), C1!=C2 .
:- in(H1,M1,C1), in(H2,M2,C2),
pref(H1,M2,P1), pref(H1,M1,P2), P1>P2,
pref(M2,H1,P3), pref(M2,H2,P4), P3>P4 .
This program (plus the EDB in your example) generates the following marriages:
in(miguel,carla,2) in(marco,paula,3) in(joao,cristina,1) in(carlos,maria,4) in(pedro,ana,5)
Optional
If you don't want to hardcode the 5 and make it work for any number of people in input, you can dynamically count the number of women (or men, assuming that it's the same).
So you can replace casamento(1..N). with:
casamento(1..N) :- N = #count{ X : mulher(X) } .

Related

ASP Clingo - getting the exact count of atoms

I'm looking forward to assign a specific count of persons to a specific shift. For example I got six persons and three different shifts. Now I have to assign exact two persons to every shift. I tried something like this but..
NOTE: this won't work, so please edit as fast as possible to misslead people, I even removed the "." after it so nobody is copying it:
person(a)
person(b)
person(c)
person(d)
person(e)
person(f)
shift("mor")
shift("aft")
shift("nig")
shiftCount(2).
{ assign(P,S) : shift(S)} = 1 :- person(P).
% DO NOT COPY THIS! SEE RIGHT ANSWER DOWN BELOW
:- #count{P : assign(P,"mor")} = K, shiftCount(K).
:- #count{P : assign(P,"aft")} = K, shiftCount(K).
:- #count{P : assign(P,"nig")} = K, shiftCount(K).
#show assign/2.
Is this possible to count the number of assigned shifts, so I can assign exactly as many people as a given number?
The output of the code above (when the "." are inserted) is:
clingo version 5.5.0
Reading from stdin
Solving...
Answer: 1
assign(a,"nig") assign(b,"aft") assign(c,"mor") assign(d,"mor")
assign(e,"mor") assign(f,"mor")
SATISFIABLE
Models : 1+
Calls : 1
Time : 0.021s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.000s
Here you can defently see, that the morning ("mor") shift is used more than two times, as difined in the shiftCount. What do I need to change to get the wanted result?
Replace your 3 lines constraints with
{assign(P,S): person(P)} == K :- shift(S), shiftCount(K).
or alternatively if you want to use the constraint writing:
:- {assign(P,S): person(P)} != K, shift(S), shiftCount(K).
First line states: For a given shiftCount K and for every shift S: the number of assignments over all people P for this shift S is K.
The constraint reads: it can not be the case for a shiftCount K and a shift S that the number of assignments over all people P to the shift S is not K.
Please do not alter your question / sample code dramatically since this may leads to the case that this answer won't work anymore.

Clingo/ASP: Best way to generate characters in a story generator

I am trying to write a story generator in Clingo.
I am trying to say "new characters can be born if existing characters give birth to them." I define new characters as entity(<int\>), which is the best way I could think of to representing entities. I cannot hardcode this as varying number of entities can be created in a story.
My code is :
% Create instances of time, only 3 for testing
time(0..2).
% Arrow of time flows forward
next_t(T, T+1) :- time(T), time(T+1).
% Entity 1 exists at time 0.
entity(1, 0).
% If an entity ever existed, that ID is taken and cannot be assigned to
% other entities
entity_id(ID) :- entity(ID, _).
% If an entity exists, he can give birth to a new entity
% The ID of the new entity will be 1 more than ID of all current entities.
birth(X, Y, T) :- entity(Y, T), X = #max{X1+1:entity_id(X1)}, time(T).
% At each time instant, only 1 entity can be born, as only 1 event can happen per time instant.
% This also should prevent infinite entities to be created.
:- birth(X1, _, T), birth(Y1, _, T), X1!=Y1.
% In case of a birth, create a new entiti the next time instant.
entity(X, T1) :- birth(X, _, T), next(T, T1).
#show entity_id/1.
#show entity/2.
#show birth/3 .
However, output is :
entity_id(1) entity(1,0) birth(2,1,0)
entity(2, 1) is never created, nor are entity(3, 2) or entity(4, 3).
What am I doing wrong? Is there a better way to do this?
You seem to be thinking that ASP statements happen in order from first to last or something like that.
But in fact they're just rules about a collection of atoms. The rules always hold. In particular, the rule:
entity_id(ID) :- entity(ID, _).
says nothing about duplicates. It just says that for every entity which has an ID ID, ID is an entity_id.
If you want to encode the rule that each ID is used once, you should write it as:
:- {entity(ID,_)} > 1; entity_id(ID).
Also you try to construct "ID's" which are "one more than all current entities", but there's no such thing as "current" entities. All we have to guide us are the time-steps.
Let's try writing this in a way that keeps our timesteps explicit throughout.
% Create instances of time, only 3 for testing
time(0..2).
% Entity eve exists at time 0.
entity(1, 0).
nextID(2, 0).
% If an entity existed at the previous time-step, they continue to exist
% at the next time-step (as I understand, no entity dies).
entity(ID, T) :- entity(ID, T-1); time(T).
% Any entity who was alive on the previous time-step can give birth to
% a child at time T. This child's ID is the current `nextID`
% Note this is a _choice_ rule. The entity _can_ give birth, they don't
% have to. Also we only allow at most one of these births to happen at
% each time-step.
{birth(ChildID, ParentID, T) : entity(ParentID,T-1)} <= 1 :- nextID(ChildID,T).
% Once born, an ID becomes an entity.
entity(ID,T) :- birth(ID,_,T).
% If an entity was born at the previous time-step, the nextID increases by one
% for this time-step.
nextID(ID+1,T) :- nextID(ID,T-1); time(T); entity(ID,T-1).
% Otherwise it stays the same.
nextID(ID,T) :- nextID(ID,T-1); time(T); not entity(ID,T-1).
#show birth/3.
Running this I find there are 5 models.
$ clingo entities.asp 0
clingo version 5.3.1
Reading from entities.asp
Solving...
Answer: 1
% ^ Nobody is ever born
Answer: 2
birth(2,1,2)
% ^ Nobody born at time 1. 1 births a child at time 2
Answer: 3
birth(2,1,1) birth(3,2,2)
% ^ 1 births a child at time 1 and that child gives birth at time 2.
Answer: 4
birth(2,1,1)
% ^ 1 births a child at time 1. Nobody is born at time 2.
Answer: 5
birth(2,1,1) birth(3,1,2)
% ^ 1 births two children; one at time 1 and another at time 2.
SATISFIABLE
Models : 5
Calls : 1
Time : 0.011s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.004s

Understanding how to read each-right and each-left combined in kdb

From q for mortals, i'm struggling to understand how to read this, and understand it logically.
1 2 3,/:\:10 20
I understand the result is a cross product when in full form: raze 1 2 3,/:\:10 20.
But reading from left to right, I'm currently lost at understanding what this yields (in my head)
\:10 20
combined with 1 2 3,/: ??
Help in understanding how to read this clearly (in words or clear logic) would be appreciated.
I found myself saying the following in my head whilst I program the syntax in q. q works from right to left.
Internal Monologue -> Join the string on the right onto each of the strings on the left
code -> "ABC",\:"-D"
result -> "A-D"
"B-D"
"C-D"
I think that's an easy way to understand it. 'join' can be replaced with whatever...
Internal Monologue -> Does the string on the right match any of the strings on the left
code -> ("Cat";"Dog";"CAT";"dog")~\:"CAT"
result -> 0010b
Each-right is the same concept and combining them is straightforward also;
Internal Monologue -> Does each of the strings on the right match each of the strings on the left
code -> ("Cat";"Dog";"CAT";"dog")~\:/:("CAT";"Dog")
result -> 0010b
0100b
So in your example 1 2 3,/:\:10 20 - you're saying 'Join each of the elements on the right to each of the elements on the left'
Hope this helps!!
EDIT To add a real world example.... - consider the following table
q)show tab:([] upper syms:10?`2; names:10?("Robert";"John";"Peter";"Jenny"); amount:10?til 10)
syms names amount
--------------------
CF "Peter" 8
BP "Robert" 1
IC "John" 9
IN "John" 5
NM "Peter" 4
OJ "Jenny" 6
BJ "Robert" 6
KH "John" 1
HJ "Peter" 8
LH "John" 5
q)
I you want to get all records where the name is Robert, you can do; select from tab where names like "Robert"
But if you want to get the results where the name is either Robert or John, then it is a perfect scenario to use our each-left and each-right.
Consider the names column - it's a list of strings (a list where each element is a list of chars). What we want to ask is 'does any of the strings in the names column match any of the strings we want to find'... that translates to (namesList)~\:/:(list;of;names;to;find). Here's the steps;
q)(tab`names)~\:/:("Robert";"John")
0100001000b
0011000101b
From that result we want a compiled list of booleans where each element is true of it is true for Robert OR John - for example, if you look at index 1 of both lists, it's 1b for Robert and 0b for John - in our result, the value at index 1 should be 1b. Index 2 should be 1b, index3 should be 1b, index4 should be 0b etc... To do this, we can apply the any function (or max or sum!). The result is then;
q)any(tab`names)~\:/:("Robert";"John")
0111001101b
Putting it all together, we get;
q)select from tab where any names~\:/:("Robert";"John")
syms names amount
--------------------
BP "Robert" 1
IC "John" 9
IN "John" 5
BJ "Robert" 6
KH "John" 1
LH "John" 5
q)
Firstly, q is executed (and hence generally read) right to left. This means that it's interpreting the \: as a modifier to be applied to the previous function, which itself is a simple join modified by the /: adverb. So the way to read this is "Apply join each-right to each of the left-hand arguments."
In this case, you're applying the two adverbs to the join - \:10 20 on its own has no real meaning here.
I find it helpful to also look at the converse case 1 2 3,\:/:10 20, running that code produces a 2x6 matrix, which I'd describe more like "apply join each-left to each of the right hand arguments" ... I hope that makes sense.
An alternative syntax which also might help is ,/:\:[1 2 3;10 20] - this might be useful as it makes it very clear what the function you're applying is, and is equivalent to your in-place notation.

Cannot mix aggregate and non-aggregate comparison with COUNT

I know this is very commom question. But I havenot still known why in my case as follows. Give me your idea about this issue:
Question: I want to count the number of user who appear in list < 3.
- First I created the "calculated Field"
- Here is my function:
If COUNT([User]) < 3 then [User] END
Finally, I count this Meseasure again to gain the final result.
Here's my example:
User
a
a
a
a
b
b
c
b
The result expected: 1 (only c)
Thanks all
Place your IF statement inside the COUNT().

Can someone explain the TI BASIC 🔺List command?

I understand that the command compares and can subtract values, but I don't see exactly how that works. I've used a TI BASIC programming tutorial site (http://tibasicdev.wikidot.com/movement-explanation) and I need clarification on 🔺List as a whole.
This portion of the code with 🔺List is as follows,:
:min(8,max(1,A+sum(ΔList(Ans={25,34→A
:min(16,max(1,B+sum(ΔList(K={24,26→B
and the website explains the code like this.:
"This is how this code works. When you press a key, its value is stored to K. We check to see if K equals one of the keys we pressed by comparing it to the lists {24,26 and {25,34. This results in a list {0,1}, {1,0}, or {0,0}. We then take the fancy command Δlist( to see whether to move up, down, left or right. What Δlist( does is quite simple. Δlist( subtracts the first element from the second in the previous list, and stores that as a new one element list, {1}, {-1}, or {0}. We then turn the list into a real number by taking the sum of the one byte list. This 1, -1, or 0 is added to A."
The ΔList( command subtracts every element in a list from its previous element. This code uses some trickery with it to compactly return 1 if a key is pressed and -1
ΔList( calculates the differences between consecutive terms of a list, and returns them in a new list.
ΔList({0,1,4,9,16,25,36})
{1 3 5 7 9 11}
That is, ΔList({0,1,4,9,16,25,36}) = {1-0, 4-1, 9-4, 16-9, 25-16, 36-25} = {1 3 5 7 9 11}.
When there are only two elements in a list, ΔList({a,b}) is therefore equal to {b-a}. Then sum(ΔList({a,b})) is equal to b-a, since that's the only term in the list. Let's say that K is 26 in your example; that is, the > key is pressed.
B+sum(ΔList(K={24,26→B Result of expression:
K 26
K={24,26 {0,1}
ΔList(K={24,26 {1} = {0 - 1}
sum(ΔList(K={24,26 -1
B [current x-position of player]
B+sum(ΔList(K={24,26→B [add 1 to current x-pos. of player]
Similarly, B will be decreased if key 24, the left key, is pressed.