0

In prolog I'm trying to unify every valid pairing of needs with resources

needs([ece2090,1,m,13,16]).
needs([ece3520,1,tu,11,14]).
needs([ece4420,1,w,13,16]).

resources([joel, [ece2090,ece2010,ece3520,ece4420],[[m,13,16]]]).
resources([sam, [ece2010,ece4420],[]]).
resources([pete, [ece3520],[[w,13,16]]]).

using this formula

make_bid([Class,Sect,Day,Ts,Te],[Name,Cap,Unavail],[Class,Sect,Day,Ts,Te,Name,_]) :-
no_conflict_all_unavailable(Day,Ts,Te,Unavail),
course_capable(Class,Cap),
writef('%w %w %w\n',[Class,Sect,Name]),
fail.

and running this test.

test(Listing) :- needs(N), resources(R), make_bid(N,R,Listing).

The point of this part of the program is to pair every class with a teacher that both has the qualifications to teach the class and is not unavailable during that time. It's supposed to give a list.

?- test(Listing).
ece3520 1 joel
ece3520 1 pete
ece4420 1 joel
ece4420 1 sam
false.

When run, the above is generated. This is correct, but it's in a format that's useless to me, since I need it to be a variable of its own to do further computations. Then the solution is to use bagof or findall, right?

So I remove the fail clause from the main part of the program and then change the test to this

test(Bag) :- needs(N), resources(R), bagof(Listing,make_bid(N,R,Listing),Bag).

but it generates this

ece3520 1 joel
Bag = [[ece3520, 1, tu, 11, 14, joel, _G4310]] 

If you look closely you'll see that there's no period at the end as well as a lack of a true/false statement. This would lead one to believe it is infinitely looping. This isn't the case however, as the Bag matrix is fully formed and I can simply type "." to end the program (instead of, you know, aborting it).

It only generates the first valid solution. Why is this happening?

  • Don't you have to make a teacher unavailable if he gives one class? I'd go with `bagof(N, needs(N), Needs)` and then recourse, since the available times change. Can't help you with your question, though. – Patrick J. S. Jan 30 '15 at 00:14
  • Oh, actually I do know that: one of your predicates is generating a open branch, that hasn't been considered yet. The smallest knowledge base I could come up as a simple case is this: `a. a:-fail.`. if you query `?- a.` You'll get first `true` and after asking for more, `false`. Some Prolog systems replace `true` with a variable binding, if there is one. So to get closer to your case, take `a(1). a(_):-fail` and query `?- a(A)`. – Patrick J. S. Jan 30 '15 at 01:00
  • 1
    try findall instead of bagof – CapelliC Jan 30 '15 at 01:43

1 Answers1

0

You've structured your test predicate so that bagof/3 is called for every instance combination of needs(N) and resources(R) and so it collects each result of make_bid in it's own bagof/3 result:

ece3520 1 joel
Bag = [[ece3520, 1, tu, 11, 14, joel, _G4310]]

The first line is the write that is in make_bid predicate. The second line is the Bag result for the single query to make_bid for one pair of needs/resources. The last argument in the list, _G4310, occurs because your predicate uses _ and it's anonymous (never used/instantiated).

Your current make_bid is designed to write the results in a loop rather than instantiate them in multiple backtracks. So that could be changed to:

make_bid([Class, Sect, Day, Ts, Te], [Name, Cap, Unavail], [Class, Sect, Day, Ts, Te, Name, _]) :-
    no_conflict_all_unavailable(Day, Ts, Te, Unavail),
    course_capable(Class, Cap).

(NOTE: I'm not sure why you have _ at the end of the 3rd list argument. What does it represent?)

If you want to collect the whole result in one list, then you canb use findall/3:

findall([Class, Sect, Name], (needs(N), resources(R), make_bid(N, R, [Class, Sect, _, _, _, Name, _]), Listings).

This will collect a list of elements that look like, [Class, Sect, Name]. You could use bagof/3 here, but you'd need an existential quantifier for the variables in the make_bid/3 call that you don't want to bind.

If you wanted the entire Listing list, then:

findall(L, (needs(N), resources(R), make_bid(N, R, L)), Listings).

But each element of Listings will be a list whose last element is an anonymous variable, since that's how make_bid/3 is structured.

lurker
  • 56,987
  • 9
  • 69
  • 103
  • I'm having another problem. First off, thank you, this has been a lot of help. I got the matrix I wanted. Problem is, I no longer want a matrix. I would like the program to produce a bids variable structured the same as needs and resources, and then I can go from there. Do you know how to do that? I feel like it's a simple edit but I don't know where to find that information. As to your question of why the _ was in there, this is a code snippet and I was experimenting. The variable just so happened to be junk at the moment. – PowerOfKaishin Feb 02 '15 at 22:36
  • @PowerOfKaishin yes, it's a straightforward change. Exactly what do you want the terms to look like? – lurker Feb 02 '15 at 23:23
  • erm, sorry to be so jumpy, but i decided to scrap that idea, at least for now. I went back to the drawing boards because matrices are the best way to do operations in prolog but they pretty much make backtracking impossible. http://stackoverflow.com/questions/28289344/prolog-finding-all-solutions – PowerOfKaishin Feb 03 '15 at 01:35