7 #include <tao/pegtl.hpp> 23 if (obj.instructorValues.size() > 0) {
25 course, FieldType::instructor, obj.instructorValues);
28 if (obj.programValues.size() > 0) {
30 course, FieldType::program, obj.programValues);
33 if (obj.segmentValues.size() > 0) {
35 course, FieldType::segment, obj.segmentValues);
38 if (obj.isMinorValues.size() > 0) {
40 course, FieldType::isMinor, obj.isMinorValues);
58 for (
unsigned j = i + 1; j < obj.courseValues.size(); j++) {
59 Clauses a = makeAntecedent(obj, obj.courseValues[j]);
61 course, obj.courseValues[j], FieldType::classroom);
66 if (obj.classNotSame) {
67 for (
unsigned j = i + 1; j < obj.courseValues.size(); j++) {
68 Clauses a = makeAntecedent(obj, obj.courseValues[j]);
70 course, obj.courseValues[j], FieldType::classroom);
76 for (
unsigned j = i + 1; j < obj.courseValues.size(); j++) {
77 Clauses a = makeAntecedent(obj, obj.courseValues[j]);
79 course, obj.courseValues[j], FieldType::slot);
84 if (obj.slotNotSame) {
85 for (
unsigned j = i + 1; j < obj.courseValues.size(); j++) {
86 Clauses a = makeAntecedent(obj, obj.courseValues[j]);
88 course, obj.courseValues[j], FieldType::slot);
93 if (obj.classValues.size() > 0) {
95 course, FieldType::classroom, obj.classValues);
98 if (obj.slotValues.size() > 0) {
100 course, FieldType::slot, obj.slotValues);
101 cons = cons & clause;
106 namespace pegtl = tao::TAO_PEGTL_NAMESPACE;
110 template <
typename Rule>
117 : pegtl::seq<pegtl::opt<pegtl::one<'-'>>, pegtl::plus<pegtl::digit>> {};
120 template <
typename Input>
121 static void apply(
const Input &in,
Object &obj) {
122 obj.integer = std::stoi(in.string());
129 struct instr : TAO_PEGTL_KEYWORD("IN") {};
135 struct notstr : TAO_PEGTL_KEYWORD("NOT") {};
138 template <
typename Input>
139 static void apply(
const Input &in,
Object &obj) {
147 struct andstr : TAO_PEGTL_KEYWORD("AND") {};
152 struct orstr : TAO_PEGTL_KEYWORD("OR") {};
166 template <
typename Input>
167 static void apply(
const Input &in,
Object &obj) {
168 obj.fieldType = FieldValuesType::CLASSROOM;
175 struct slotstr : TAO_PEGTL_KEYWORD("SLOT") {};
178 template <
typename Input>
179 static void apply(
const Input &in,
Object &obj) {
180 obj.fieldType = FieldValuesType::SLOT;
190 template <
typename Input>
191 static void apply(
const Input &in,
Object &obj) {
192 obj.fieldType = FieldValuesType::COURSE;
202 template <
typename Input>
203 static void apply(
const Input &in,
Object &obj) {
204 obj.fieldType = FieldValuesType::INSTRUCTOR;
214 template <
typename Input>
215 static void apply(
const Input &in,
Object &obj) {
216 obj.fieldType = FieldValuesType::SEGMENT;
226 template <
typename Input>
227 static void apply(
const Input &in,
Object &obj) {
228 obj.fieldType = FieldValuesType::ISMINOR;
238 template <
typename Input>
239 static void apply(
const Input &in,
Object &obj) {
240 obj.fieldType = FieldValuesType::PROGRAM;
259 : pegtl::sor<instructorstr, segmentstr, isminorstr, programstr> {};
262 template <
typename Input>
263 static void apply(
const Input &in,
Object &obj) {
265 obj.classSame =
false;
266 obj.slotSame =
false;
267 obj.classNotSame =
false;
268 obj.slotNotSame =
false;
276 : pegtl::plus<pegtl::sor<pegtl::range<'a', 'z'>, pegtl::range<'A', 'Z'>,
277 pegtl::digit, pegtl::one<'.'>, pegtl::one<'-'>,
278 pegtl::one<'@'>, pegtl::one<'<'>, pegtl::one<'>'>,
282 template <
typename Input>
283 static void apply(
const Input &in,
Object &obj) {
284 std::string val = in.string();
286 if (obj.fieldType == FieldValuesType::INSTRUCTOR) {
287 for (
unsigned i = 0; i < obj.timetabler->
data.
instructors.size(); i++) {
290 obj.instructorValues.push_back(i);
295 LOG(ERROR) <<
"Instructor " << val <<
" does not exist.";
298 }
else if (obj.fieldType == FieldValuesType::COURSE) {
299 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
300 if (obj.timetabler->
data.
courses[i].getName() == val) {
302 obj.courseValues.push_back(i);
307 LOG(ERROR) <<
"Course " << val <<
" does not exist.";
310 }
else if (obj.fieldType == FieldValuesType::SEGMENT) {
311 for (
unsigned i = 0; i < obj.timetabler->
data.
segments.size(); i++) {
312 if (obj.timetabler->
data.
segments[i].getName() == val) {
314 obj.segmentValues.push_back(i);
319 LOG(ERROR) <<
"Segment " << val <<
" does not exist.";
322 }
else if (obj.fieldType == FieldValuesType::PROGRAM) {
323 for (
unsigned i = 0; i < obj.timetabler->
data.
programs.size(); i++) {
324 if (obj.timetabler->
data.
programs[i].getNameWithType() == val) {
326 obj.programValues.push_back(i);
331 LOG(ERROR) <<
"Program " << val <<
" does not exist.";
334 }
else if (obj.fieldType == FieldValuesType::ISMINOR) {
335 for (
unsigned i = 0; i < obj.timetabler->
data.
isMinors.size(); i++) {
336 if (obj.timetabler->
data.
isMinors[i].getName() == val) {
338 obj.isMinorValues.push_back(i);
343 LOG(ERROR) <<
"IsMinor " << val <<
" does not exist.";
346 }
else if (obj.fieldType == FieldValuesType::CLASSROOM) {
347 for (
unsigned i = 0; i < obj.timetabler->
data.
classrooms.size(); i++) {
350 obj.classValues.push_back(i);
355 LOG(ERROR) <<
"Classroom " << val <<
" does not exist.";
358 }
else if (obj.fieldType == FieldValuesType::SLOT) {
359 for (
unsigned i = 0; i < obj.timetabler->
data.
slots.size(); i++) {
360 if (obj.timetabler->
data.
slots[i].getName() == val) {
362 obj.slotValues.push_back(i);
367 LOG(ERROR) <<
"Slot " << val <<
" does not exist.";
377 struct allvalues : pegtl::pad<pegtl::one<'*'>, pegtl::space> {};
380 template <
typename Input>
381 static void apply(
const Input &in,
Object &obj) {
382 std::string val = in.string();
383 if (obj.fieldType == FieldValuesType::INSTRUCTOR) {
384 for (
unsigned i = 0; i < obj.timetabler->
data.
instructors.size(); i++) {
385 obj.instructorValues.push_back(i);
387 }
else if (obj.fieldType == FieldValuesType::COURSE) {
388 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
389 obj.courseValues.push_back(i);
391 }
else if (obj.fieldType == FieldValuesType::SEGMENT) {
392 for (
unsigned i = 0; i < obj.timetabler->
data.
segments.size(); i++) {
393 obj.segmentValues.push_back(i);
395 }
else if (obj.fieldType == FieldValuesType::PROGRAM) {
396 for (
unsigned i = 0; i < obj.timetabler->
data.
programs.size(); i++) {
397 obj.programValues.push_back(i);
399 }
else if (obj.fieldType == FieldValuesType::ISMINOR) {
400 for (
unsigned i = 0; i < obj.timetabler->
data.
isMinors.size(); i++) {
401 obj.isMinorValues.push_back(i);
403 }
else if (obj.fieldType == FieldValuesType::CLASSROOM) {
404 for (
unsigned i = 0; i < obj.timetabler->
data.
classrooms.size(); i++) {
405 obj.classValues.push_back(i);
407 }
else if (obj.fieldType == FieldValuesType::SLOT) {
408 for (
unsigned i = 0; i < obj.timetabler->
data.
slots.size(); i++) {
409 obj.slotValues.push_back(i);
419 struct sameval : pegtl::pad<TAO_PEGTL_KEYWORD("SAME"), pegtl::space> {};
422 template <
typename Input>
423 static void apply(
const Input &in,
Object &obj) {
424 if (obj.fieldType == FieldValuesType::CLASSROOM) {
425 obj.classSame =
true;
426 }
else if (obj.fieldType == FieldValuesType::SLOT) {
436 struct notsameval : pegtl::pad<TAO_PEGTL_KEYWORD("NOTSAME"), pegtl::space> {};
439 template <
typename Input>
440 static void apply(
const Input &in,
Object &obj) {
441 if (obj.fieldType == FieldValuesType::CLASSROOM) {
442 obj.classNotSame =
true;
443 }
else if (obj.fieldType == FieldValuesType::SLOT) {
444 obj.slotNotSame =
true;
453 : pegtl::seq<pegtl::pad<pegtl::one<'{'>, pegtl::space>,
454 pegtl::list<value, pegtl::one<','>, pegtl::space>,
455 pegtl::pad<pegtl::one<'}'>, pegtl::space>> {};
460 struct values : pegtl::sor<allvalues, listvalues, sameval, notsameval> {};
466 : pegtl::seq<pegtl::pad<classroomstr, pegtl::space>, values> {};
471 struct slotdecl : pegtl::seq<pegtl::pad<slotstr, pegtl::space>, values> {};
477 : pegtl::seq<pegtl::pad<coursestr, pegtl::space>, values> {};
480 template <
typename Input>
481 static void apply(
const Input &in,
Object &obj) {
482 obj.courseExcept =
false;
490 : pegtl::seq<pegtl::pad<coursestr, pegtl::space>,
491 pegtl::pad<exceptstr, pegtl::space>, values> {};
494 template <
typename Input>
495 static void apply(
const Input &in,
Object &obj) {
496 obj.courseExcept =
true;
503 struct coursedecl : pegtl::sor<coursenoexceptdecl, courseexceptdecl> {};
506 template <
typename Input>
507 static void apply(
const Input &in,
Object &obj) {
515 struct decl : pegtl::sor<slotdecl, classroomdecl> {};
520 struct decls : pegtl::list<decl, andstr, pegtl::space> {};
525 struct fielddecl : pegtl::seq<pegtl::pad<fieldtype, pegtl::space>, values> {};
530 struct fielddecls : pegtl::opt<pegtl::list<fielddecl, andstr, pegtl::space>> {};
536 pegtl::pad<instr, pegtl::space>, decls> {};
539 template <
typename Input>
540 static void apply(
const Input &in,
Object &obj) {
542 if (obj.courseExcept) {
543 std::vector<int> courseVals;
544 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
545 if (std::find(obj.courseValues.begin(), obj.courseValues.end(), i) ==
546 obj.courseValues.end()) {
547 courseVals.push_back(i);
550 obj.courseValues = courseVals;
552 for (
unsigned i = 0; i < obj.courseValues.size(); i++) {
553 int course = obj.courseValues[i];
555 ante = makeAntecedent(obj, course);
556 cons = makeConsequent(obj, course, i);
560 clause = ante >> cons;
561 clauses = clauses & clause;
563 obj.constraint = clauses;
564 obj.courseValues.clear();
565 obj.instructorValues.clear();
566 obj.isMinorValues.clear();
567 obj.programValues.clear();
568 obj.segmentValues.clear();
569 obj.classValues.clear();
570 obj.slotValues.clear();
572 obj.classSame =
false;
573 obj.slotSame =
false;
574 obj.classNotSame =
false;
575 obj.slotNotSame =
false;
585 : pegtl::seq<pegtl::if_must<pegtl::pad<pegtl::one<'('>, pegtl::space>,
587 pegtl::pad<pegtl::one<')'>, pegtl::space>>> {};
593 : pegtl::seq<pegtl::pad<notstr, pegtl::space>, constraint_braced> {};
596 template <
typename Input>
597 static void apply(
const Input &in,
Object &obj) {
598 Clauses clauses = obj.constraint;
599 obj.constraint = ~clauses;
608 : pegtl::sor<constraint_expr, constraint_not, constraint_braced> {};
611 template <
typename Input>
612 static void apply(
const Input &in,
Object &obj) {
613 obj.constraintVals.push_back(obj.constraint);
624 template <
typename Input>
625 static void apply(
const Input &in,
Object &obj) {
626 Clauses clauses = obj.constraintVals[0];
627 for (
unsigned i = 1; i < obj.constraintVals.size(); i++) {
628 clauses = clauses & obj.constraintVals[i];
630 obj.constraintVals.clear();
631 obj.constraintAnds.push_back(clauses);
642 template <
typename Input>
643 static void apply(
const Input &in,
Object &obj) {
644 Clauses clauses = obj.constraintAnds[0];
645 for (
unsigned i = 1; i < obj.constraintAnds.size(); i++) {
646 clauses = clauses | obj.constraintAnds[i];
648 obj.constraintAnds.clear();
649 obj.constraint = clauses;
657 : pegtl::seq<coursedecl, pegtl::pad<unbundlestr, pegtl::space>, fielddecls,
658 pegtl::opt<notstr>, pegtl::pad<instr, pegtl::space>, decl,
659 pegtl::pad<weightstr, pegtl::space>,
660 pegtl::pad<integer, pegtl::space>> {};
663 template <
typename Input>
664 static void apply(
const Input &in,
Object &obj) {
665 if (obj.courseExcept) {
666 std::vector<int> courseVals;
667 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
668 if (std::find(obj.courseValues.begin(), obj.courseValues.end(), i) ==
669 obj.courseValues.end()) {
670 courseVals.push_back(i);
673 obj.courseValues = courseVals;
675 for (
unsigned i = 0; i < obj.courseValues.size(); i++) {
676 int course = obj.courseValues[i];
678 ante = makeAntecedent(obj, course);
679 cons = makeConsequent(obj, course, i);
683 clause = ante >> cons;
684 obj.constraint = clause;
686 obj.timetabler->
newVar());
688 if (obj.integer != 0) {
692 obj.timetabler->
addClauses(hardConsequent, -1);
697 obj.courseValues.clear();
698 obj.instructorValues.clear();
699 obj.isMinorValues.clear();
700 obj.programValues.clear();
701 obj.segmentValues.clear();
702 obj.classValues.clear();
703 obj.slotValues.clear();
705 obj.classSame =
false;
706 obj.slotSame =
false;
707 obj.classNotSame =
false;
708 obj.slotNotSame =
false;
716 struct wconstraint : pegtl::seq<pegtl::pad<constraint_or, pegtl::space>,
717 pegtl::pad<weightstr, pegtl::space>,
718 pegtl::pad<integer, pegtl::space>> {};
721 template <
typename Input>
722 static void apply(
const Input &in,
Object &obj) {
724 obj.timetabler->
newVar());
726 if (obj.integer != 0) {
730 obj.timetabler->
addClauses(hardConsequent, -1);
741 pegtl::must<pegtl::star<pegtl::sor<wconstraint, constraint_unbundle>>,
744 template <
typename Rule>
746 template <
typename Input,
typename... States>
747 static void raise(
const Input &in, States &&...) {
748 LOG(ERROR) << in.position() <<
" Error parsing custom constraints";
766 obj.constraintEncoder = constraintEncoder;
768 pegtl::file_input<> in(file);
781 classNotSame =
false;
Parse "NOTSAME": Used to specify constraints on courses with different field values.
Parse disjunction of constraints The combined clauses for all the constraints are stored in obj...
Parse "SEGMENT": Similar to classroom.
Parse "SAME": Used to specify constraints on courses with same field values.
Parse "NOT": Store that NOT keyword is present in the custom constraint.
Parse courses declaration without except keyword.
Class for representing a clause.
Parse a constraint with unbundle keyword.
Object()
Initialize object members.
std::vector< Segment > segments
Clauses hasSameFieldTypeAndValue(int, int, FieldType)
Gives Clauses that represent that a pair of courses have the same field value for a given FieldType...
Constraint is on one of the instructor, segment, isminor, program. isNot, classSame, slotSame, classNotSame, slotNotSame are reset.
std::vector< Classroom > classrooms
Parse integer: Store the integer in the object.
std::vector< Slot > slots
Parse "SLOT": Similar to classroom.
std::vector< Var > customConstraintVars
std::vector< IsMinor > isMinors
Parse a value of the field that is specified in the constraint.
Parse multi decls in consequent of the constraint.
std::vector< Instructor > instructors
Class for constraint encoder.
Struct for the type used by actions in the parser.
Clauses hasFieldTypeListedValues(int, FieldType, std::vector< int >)
Gives Clauses that represent that a Course has a field value for a given FieldType out of a list of p...
Parse courses declaration with except keyword.
Parse single decl in consequent of the constraint.
Parse constraint enclosed in braces.
Parse * as all values of the specified field.
Parse "PROGRAM": Similar to classroom.
Parse multi field decls in antecedent of the constraint.
Parse "INSTRUCTOR": Similar to classroom.
std::map< int, unsigned > customMap
Parse list of values of a field specified in the constraint.
std::vector< Course > courses
Parse "CLASSROOM": Store the field type to be classroom which will be used while forming the custom c...
Parse a constraint: Constraint expression or negation of some constraint expression or a constraint e...
Parse conjunction of constraints Add all the constraints to obj.constraintAdds.
Class for representing a set of clauses.
Parse "ISMNOR": Similar to classroom.
Parse fieldd decl in antecedent of the constraint.
Parse weighted constraint Add the clauses corresponding to the constraint along with its weight...
Parse negation of a constraint.
void parseCustomConstraints(std::string file, ConstraintEncoder *constraintEncoder, Timetabler *timetabler)
Parses custom constraints given in a file and adds them to the solver.
std::vector< Program > programs
Parse "COURSE": Similar to classroom.
Parse constraints from the file, generate error on failure.