1% THIS FILE CONTAINS THE SORTED LIST OF COURSES IMPLEMENTATION OF has_courses
    2
    3% The following example shows how we can combine databases and
    4% sophisticated rules in order to represent non-trivial regulations
    5% of a university. This is intended to show a knowledge-based
    6% application of our definite clause language.
    7
    8
    9% This assumes that we have databases about individual students and about
   10% what grades they achieved in different courses.
   11
   12% grade(St,Course,Mark) is true if student St achieved Mark in Course.
   13grade(david,engl101,87).
   14grade(david,phys101,89).
   15grade(david,chem101,67).
   16grade(david,math101,77).
   17grade(david,cs126,84).
   18grade(david,cs202,88).
   19grade(david,geol101,74).
   20grade(david,phys202,92).
   21grade(david,math202,81).
   22grade(david,cs204,87).
   23grade(david,hist101,66).
   24grade(david,cs333,77).
   25grade(david,cs312,74).
   26grade(david,math302,41).
   27grade(david,math302,87).
   28grade(david,cs304,79).
   29grade(david,cs804,80).
   30grade(david,psyc303,85).
   31grade(david,stats324,91).
   32grade(david,cs405,77).
   33
   34% We also have database relations about the structure of the university,
   35% and information about different courses.
   36% dept(Dept,Fac) is true if department Dept is in faculty Fac
   37dept(history,arts).
   38dept(english,arts).
   39dept(psychology,science).
   40dept(statistics,science).
   41dept(mathematics,science).
   42dept(cs,science).
   43
   44% course(Course,Dept,Level) is true if Course is a course in department Dept,
   45% at level Level.
   46course(hist101,history,first).
   47course(engl101,english,first).
   48course(psyc303,psychology,third).
   49course(stats324,statistics,third).
   50course(math302,mathematics,third).
   51course(phys101,physics,first).
   52
   53% We can use rules to represent what is needed for degree requirements. Here
   54% we give the subset of the degree requirements for a fictional university that
   55% are applicable for computer science students.
   56% These will be used to illustrate the power of our representation.
   57
   58% completed_degree(St,Dept) is true if student St has completed a four-year 
   59% degree in department Dept. In order to have satisfied these requirements,
   60% the student must have covered the core courses of the department, satisfied
   61% the faculty requirements of the faculty in which the department is, they
   62% must have fulfilled the electives requirement, and must have enough units.
   63satisfied_degree_requirements(St,Dept) <-
   64   covers_core_courses(St,Dept) &
   65   dept(Dept,Fac) &
   66   satisfies_faculty_req(Fac,St) &
   67   fulfilled_electives(St,Dept) &
   68   enough_units(St,Dept).
   69
   70% covers_core_courses(St,Dept) is true if student St has covered the core 
   71% courses for department Dept.
   72covers_core_courses(St,Dept) <-
   73   core_courses(Dept,CC,MinPass) &
   74   passed_each(CC,St,MinPass).
   75
   76% core_courses(Dept,CC,MinPass) is true if CC is the list of core courses
   77% for department Dept, and MinPass is the passing grade for these core courses.
   78
   79% The core courses for a cs degree are cs202, math202, cs204, cs304 and math302
   80% The student must pass each with at least 65% to pass
   81core_courses(cs,[cs202,math202,cs204,cs304,math302],65).
   82
   83% passed_each(CL,St,MinPass) is true if student St has a grade of at least
   84% MinPass in each course in the courses in list CL of courses.
   85passed_each([],_,_).
   86passed_each([C|R],St,MinPass) <-
   87   passed(St,C,MinPass) &
   88   passed_each(R,St,MinPass).
   89
   90% passed(St,C,MinPass) is true if student St has a grade of at least
   91% MinPass in course C
   92passed(St,C,MinPass) <-
   93   grade(St,C,Gr) &
   94   Gr >= MinPass.
   95
   96% The faculty requirements for the science faculty are that a student must 
   97% have passed (i.e., have greater than 50%)
   98% in engl101, phys101, chem101, math101, either cs101 or stats101 and
   99% either biol101, geol101 or astr101.
  100satisfies_faculty_req(science,St) <-
  101   passed_each([engl101,phys101,chem101,math101],St,50) &
  102   passed_one([cs126,stats101],St,50) &
  103   passed_one([bil101,geol101,astr101],St,50).
  104
  105% passed_one(CL,St,MinPass) is true if student St has a grade of at least
  106% MinPass in one of the courses in the courses in list CL of courses.
  107passed_one(CL,St,MinPass) <-
  108   member(C,CL) &
  109   passed(St,C,MinPass).
  110
  111
  112% fulfilled_electives(St,Dept) is student St has fulfilled the elective 
  113% requirements for department Dept.
  114% A student in a science department needs an arts course 
  115% (other than engl101) &
  116% and two science courses from departments other than their own.
  117% The science courses have to be third or fourth year courses.
  118fulfilled_electives(St,SciDept) <-
  119   dept(SciDept,science) &
  120   has_arts_elective(St) &
  121   has_sci_elective(St,SciDept,Sci1) &
  122   has_sci_elective(St,SciDept,Sci2) &
  123   Sci1 \= Sci2.
  124
  125% has_arts_elective(St) is true if student St has passed an arts course 
  126% (other than engl101)
  127has_arts_elective(St) <-
  128   passed(St,ArtsEl,50) &
  129   course(ArtsEl,ArtsDept,_) &
  130   dept(ArtsDept,arts) &
  131   ArtsEl \= engl101.
  132
  133% has_sci_elective(St,Major,SciC) is true if SciC is a third or fourth year 
  134% course passed by student 
  135% St. SciC must be in a science department other than department Major.
  136has_sci_elective(St,Major,SciC) <-
  137   passed(St,SciC,50) &
  138   course(SciC,Dept,Level) &
  139   Dept \= Major &
  140   dept(Dept,science) &
  141   member(Level,[third,fourth]).
  142
  143% enough_units(St,Dept) is true if student St has enough units for a degree
  144% in department Dept.
  145enough_units(St,SciDept) <-
  146   dept(SciDept,science) &
  147   has_courses(St,_,18,50).
  148
  149% has_courses(St,L,N,MinPass) is true if L is a list of N courses that student 
  150% St has passed with a grade of at least MinPass.
  151has_courses(_,[],0,_).
  152has_courses(St,[C],1,MinPass) <-
  153   passed(St,C,MinPass).
  154has_courses(St,[C,C1|R],N1,MinPass) <-
  155   N is N1-1 &
  156   has_courses(St,[C1|R],N,MinPass) &
  157   passed(St,C,MinPass) &
  158   C @< C1.
  159% C @< C1 is true if C is alphabetically before C1.
  160
  161% member(X,L) is true if X is an element of list L
  162member(X,[X|_]).
  163member(X,[_|R]) <-
  164   member(X,R).
  165
  166% notin(X,L) is true if X is not an element of list L
  167notin(_,[]).
  168notin(A,[H|T]) <-
  169   A \= H &
  170   notin(A,T).
  171
  172% Exercises: fix up our knowledge base so that a student cannot count core courses as electives.
  173% Explain why the inequality is needed at the end of the definition of fulfilled_electives.
  174% Explain why enough_units constructs a list of the courses taken. What is
  175% the major efficiency problem with this procedure? How can this be fixed?