(Noob here.) Say I have a degree that requires a student to take CS1 and CS2 and (CS3 or CS4). I'd like to use ASP to get a list of courses a student could take to fulfill the degree requirements. Specifically, I'd expect the answer to be {CS1, CS2, CS3} and {CS1, CS2, and CS4}.
So far, I've come up with the following rules:
course(cs_1,1).
course(cs_2,2).
course(cs_3,3).
course(cs_4,3).
requirement(X) :- course(_,X).
where course(A,B) indicates that A is a course that fulfills requirement B. This is where I am stumped. I'm not sure how to tell clingo that I'm looking for a set of sets that meets the requirements. Reviewing the documentation at https://potassco.org/doc/ has been helpful but most of the examples seem to me (in my ignorance) to have a fixed number of output variables.
The main issue with your current approach is that it has already defined what each course requires as facts. This means that none of these facts can be contradicted without making the program unsatisfiable. What we need to solve the problem you have posed is a disjunction between the courses that have the same requirements. If we define our facts like the following:
% fulfills(course, requirement)
fulfills(cs_1,1).
fulfills(cs_2,2).
fulfills(cs_3,3) | fulfills(cs_4,3).
it becomes much easier to define a rule to get us the info we want. From this list of facts, we can see that we cs_1 fulfills requirement 1, cs_2 fulfills requirement 2, and either cs_3 or cs_4 fulfills requirement 3. This means that we cannot have both fulfills(cs_3,3)
and fulfills(cs_4,3)
in our answer set. Instead, we can have only one of these facts since if we had both our set would not be minimal.
Although we could write some rules to pare down the answer sets that this generates or define more relationships, the program is good as-is! It generates the following, which matches your desired results:
Answer: 1
fulfills(cs_1,1) fulfills(cs_2,2) fulfills(cs_3,3)
Answer: 2
fulfills(cs_1,1) fulfills(cs_2,2) fulfills(cs_4,3)
SATISFIABLE
Models : 2
Calls : 1
Time : 0.001s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.000s
We can then extend it to more courses and requirements:
fulfills(cs_1,1).
fulfills(cs_2,2) | fulfills(cs_3,2).
fulfills(cs_4,3) | fulfills(cs_5,3).
fulfills(cs_6,4) | fulfills(cs_7,4) | fulfills(cs_8,4).
fulfills(cs_9, 5).
which gives us a lot more possibilities:
Answer: 1
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_6,4) fulfills(cs_4,3) fulfills(cs_2,2)
Answer: 2
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_6,4) fulfills(cs_4,3) fulfills(cs_3,2)
Answer: 3
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_6,4) fulfills(cs_5,3) fulfills(cs_2,2)
Answer: 4
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_6,4) fulfills(cs_5,3) fulfills(cs_3,2)
Answer: 5
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_8,4) fulfills(cs_4,3) fulfills(cs_3,2)
Answer: 6
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_8,4) fulfills(cs_5,3) fulfills(cs_3,2)
Answer: 7
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_8,4) fulfills(cs_4,3) fulfills(cs_2,2)
Answer: 8
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_8,4) fulfills(cs_5,3) fulfills(cs_2,2)
Answer: 9
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_7,4) fulfills(cs_4,3) fulfills(cs_3,2)
Answer: 10
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_7,4) fulfills(cs_4,3) fulfills(cs_2,2)
Answer: 11
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_7,4) fulfills(cs_5,3) fulfills(cs_3,2)
Answer: 12
fulfills(cs_1,1) fulfills(cs_9,5) fulfills(cs_7,4) fulfills(cs_5,3) fulfills(cs_2,2)
SATISFIABLE
Models : 12
Calls : 1
Time : 0.002s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s)
CPU Time : 0.000s
if we want, we could even drop the second argument to fulfills
since we're not using it for anything yet. The following yields the same results as our first example:
course(cs_1).
course(cs_2).
course(cs_3) | course(cs_4).
Typically, we will start an answer set program by defining all of our possible facts and their disjunctions and then limiting them with rules. For this program we have a rather small starting set, but they can get quite large so complex rules can come in handy. However, for this problem we don't need any!
(Hey Dr. Ricks, this is Isaac from Game Programming/Image Processing! Stumbled upon your question, hopefully my answer is helpful!)