Timetabler
constraint_adder.cpp
1 #include "constraint_adder.h"
2 
3 #include <iostream>
4 #include <vector>
5 #include "clauses.h"
6 #include "constraint_encoder.h"
7 #include "core/SolverTypes.h"
8 #include "global.h"
9 #include "timetabler.h"
10 #include "utils.h"
11 
12 using namespace NSPACE;
13 
22  this->encoder = encoder;
23  this->timetabler = timetabler;
24 }
25 
39 Clauses ConstraintAdder::fieldSingleValueAtATime(FieldType fieldType) {
40  Clauses result;
41  result.clear();
42  std::vector<Course> courses = timetabler->data.courses;
43  for (unsigned i = 0; i < courses.size(); i++) {
44  for (unsigned j = i + 1; j < courses.size(); j++) {
45  /*
46  * For every pair of courses, either the field value of the
47  * FieldType is different or their times do not intersect
48  */
49  Clauses antecedent =
50  encoder->hasSameFieldTypeNotSameValue(i, j, fieldType);
51  Clauses consequent = encoder->notIntersectingTime(i, j);
52  result.addClauses(antecedent | consequent);
53  }
54  }
55  return result;
56 }
57 
67 Clauses ConstraintAdder::instructorSingleCourseAtATime() {
68  return fieldSingleValueAtATime(FieldType::instructor);
69 }
70 
80 Clauses ConstraintAdder::classroomSingleCourseAtATime() {
81  return fieldSingleValueAtATime(FieldType::classroom);
82 }
83 
93 Clauses ConstraintAdder::programSingleCoreCourseAtATime() {
94  Clauses result;
95  result.clear();
96  std::vector<Course> courses = timetabler->data.courses;
97  for (unsigned i = 0; i < courses.size(); i++) {
98  for (unsigned j = i + 1; j < courses.size(); j++) {
99  /*
100  * For every pair of courses, either there is no Program for which
101  * they are both core or their times do not intersect
102  */
103  Clauses antecedent = encoder->hasNoCommonCoreProgram(i, j);
104  Clauses consequent = encoder->notIntersectingTime(i, j);
105  result.addClauses(antecedent | consequent);
106  }
107  }
108  return result;
109 }
110 
119 std::vector<Clauses> ConstraintAdder::minorInMinorTime() {
120  std::vector<Course> courses = timetabler->data.courses;
121  std::vector<Clauses> result(courses.size());
122  for (unsigned i = 0; i < courses.size(); i++) {
123  result[i].clear();
124  /*
125  * a minor course must be in a minor Slot.
126  * a non-minor course must not be in a minor Slot.
127  */
128  Clauses antecedent = encoder->isMinorCourse(i);
129  Clauses consequent = encoder->slotInMinorTime(i);
130  result[i].addClauses(antecedent >> consequent);
131  result[i].addClauses(consequent >> antecedent);
132  }
133  return result;
134 }
135 
150 std::vector<Clauses> ConstraintAdder::exactlyOneFieldValuePerCourse(
151  FieldType fieldType) {
152  std::vector<Course> courses = timetabler->data.courses;
153  std::vector<Clauses> result(courses.size());
154  for (unsigned i = 0; i < courses.size(); i++) {
155  result[i].clear();
156  // exactly one field value must be true
157  Clauses exactlyOneFieldValue =
158  encoder->hasExactlyOneFieldValueTrue(i, fieldType);
159  Clauses cclause(timetabler->data.highLevelVars[i][fieldType]);
160  // high level variable implies the clause, and by default is hard
161  // if high level variable is false, this clause could not be satisfied
162  // this provides a reason to the user
163  result[i].addClauses(cclause >> exactlyOneFieldValue);
164  }
165  return result;
166 }
167 
178  const Clauses &clauses,
179  const int course) {
180  if (course == -1) {
181  if (timetabler->data.predefinedClausesWeights[clauseType] != 0) {
182  Clauses hardConsequent =
183  CClause(timetabler->data.predefinedConstraintVars[clauseType][0]) >>
184  clauses;
185  timetabler->addClauses(hardConsequent, -1);
186  }
187  timetabler->addHighLevelConstraintClauses(clauseType, -1);
188  } else {
189  if (timetabler->data.predefinedClausesWeights[clauseType] != 0) {
190  Clauses hardConsequent =
191  CClause(
192  timetabler->data.predefinedConstraintVars[clauseType][course]) >>
193  clauses;
194  timetabler->addClauses(hardConsequent, -1);
195  }
196  timetabler->addHighLevelConstraintClauses(clauseType, course);
197  }
198 }
199 
205  std::vector<int> weights = timetabler->data.predefinedClausesWeights;
206  // add the constraints to the formula
207  addSingleConstraint(PredefinedClauses::instructorSingleCourseAtATime,
208  instructorSingleCourseAtATime(), -1);
209  addSingleConstraint(PredefinedClauses::classroomSingleCourseAtATime,
210  classroomSingleCourseAtATime(), -1);
211  addSingleConstraint(PredefinedClauses::programSingleCoreCourseAtATime,
212  programSingleCoreCourseAtATime(), -1);
213 
214  auto clauses = minorInMinorTime();
215  for (unsigned i = 0; i < clauses.size(); i++) {
216  addSingleConstraint(PredefinedClauses::minorInMinorTime, clauses[i], i);
217  }
218 
219  clauses = programAtMostOneOfCoreOrElective();
220  for (unsigned i = 0; i < clauses.size(); i++) {
221  addSingleConstraint(PredefinedClauses::programAtMostOneOfCoreOrElective,
222  clauses[i], i);
223  }
224 
225  clauses = exactlyOneFieldValuePerCourse(FieldType::slot);
226  for (unsigned i = 0; i < clauses.size(); i++) {
227  addSingleConstraint(PredefinedClauses::exactlyOneSlotPerCourse, clauses[i],
228  i);
229  }
230 
231  clauses = exactlyOneFieldValuePerCourse(FieldType::classroom);
232  for (unsigned i = 0; i < clauses.size(); i++) {
233  addSingleConstraint(PredefinedClauses::exactlyOneClassroomPerCourse,
234  clauses[i], i);
235  }
236 
237  clauses = exactlyOneFieldValuePerCourse(FieldType::instructor);
238  for (unsigned i = 0; i < clauses.size(); i++) {
239  addSingleConstraint(PredefinedClauses::exactlyOneInstructorPerCourse,
240  clauses[i], i);
241  }
242 
243  clauses = exactlyOneFieldValuePerCourse(FieldType::isMinor);
244  for (unsigned i = 0; i < clauses.size(); i++) {
245  addSingleConstraint(PredefinedClauses::exactlyOneIsMinorPerCourse,
246  clauses[i], i);
247  }
248 
249  clauses = exactlyOneFieldValuePerCourse(FieldType::segment);
250  for (unsigned i = 0; i < clauses.size(); i++) {
251  addSingleConstraint(PredefinedClauses::exactlyOneSegmentPerCourse,
252  clauses[i], i);
253  }
254 
255  clauses = coreInMorningTime();
256  for (unsigned i = 0; i < clauses.size(); i++) {
257  addSingleConstraint(PredefinedClauses::coreInMorningTime, clauses[i], i);
258  }
259 
260  clauses = electiveInNonMorningTime();
261  for (unsigned i = 0; i < clauses.size(); i++) {
262  addSingleConstraint(PredefinedClauses::electiveInNonMorningTime, clauses[i],
263  i);
264  }
265 }
266 
267 /*Clauses ConstraintAdder::softConstraints() {
268  return existingAssignmentClausesSoft();
269 }*/
270 
278 std::vector<Clauses> ConstraintAdder::coreInMorningTime() {
279  std::vector<Course> courses = timetabler->data.courses;
280  std::vector<Clauses> result(courses.size());
281  for (unsigned i = 0; i < courses.size(); i++) {
282  result[i].clear();
283  Clauses coreCourse = encoder->isCoreCourse(i);
284  Clauses morningTime = encoder->courseInMorningTime(i);
285  result[i].addClauses(coreCourse >> morningTime);
286  }
287  return result;
288 }
289 
297 std::vector<Clauses> ConstraintAdder::electiveInNonMorningTime() {
298  std::vector<Course> courses = timetabler->data.courses;
299  std::vector<Clauses> result(courses.size());
300  for (unsigned i = 0; i < courses.size(); i++) {
301  result[i].clear();
302  Clauses coreCourse = encoder->isElectiveCourse(i);
303  Clauses morningTime = encoder->courseInMorningTime(i);
304  result[i].addClauses(coreCourse >> (~morningTime));
305  }
306  return result;
307 }
308 
318 std::vector<Clauses> ConstraintAdder::programAtMostOneOfCoreOrElective() {
319  std::vector<Course> courses = timetabler->data.courses;
320  std::vector<Clauses> result(courses.size());
321  for (unsigned i = 0; i < courses.size(); i++) {
322  result[i].clear();
323  result[i].addClauses(encoder->programAtMostOneOfCoreOrElective(i));
324  }
325  return result;
326 }
void addConstraints()
Adds all the constraints with their respective weights using the Timetabler object to the solver...
std::vector< int > predefinedClausesWeights
Definition: data.h:124
Class for representing a clause.
Definition: cclause.h:21
Class for time tabler.
Definition: timetabler.h:44
std::vector< std::vector< Var > > predefinedConstraintVars
Definition: data.h:85
PredefinedClauses
Enum that represents all the predefined constraints.
Definition: global.h:14
Class for constraint encoder.
Timetabler * timetabler
Definition: main.cpp:90
FieldType
Enum that represents all the field types.
Definition: global.h:9
void addSingleConstraint(PredefinedClauses, const Clauses &, const int course)
Adds a single predefined constraint to the solver.
void addClauses(const CClause &)
Adds a CClause to the set of clauses.
Definition: clauses.cpp:238
std::vector< Course > courses
Definition: data.h:36
void clear()
Clears the Clauses object by removing all the clauses.
Definition: clauses.cpp:279
std::vector< std::vector< Var > > highLevelVars
Definition: data.h:81
void addHighLevelConstraintClauses(PredefinedClauses, const int course)
Adds high level clauses for predefined constraints.
Definition: timetabler.cpp:72
Class for representing a set of clauses.
Definition: clauses.h:23
void addClauses(const std::vector< CClause > &, int)
Adds clauses to the solver with specified weights.
Definition: timetabler.cpp:35
Data data
Definition: timetabler.h:63
ConstraintAdder(ConstraintEncoder *, Timetabler *)
Constructs the ConstraintAdder object.