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;
265 : pegtl::sor<instructorstr, segmentstr, isminorstr, programstr> {};
268 template <
typename Input>
269 static void apply(
const Input &in,
Object &obj) {
271 obj.classSame =
false;
272 obj.slotSame =
false;
273 obj.classNotSame =
false;
274 obj.slotNotSame =
false;
282 : pegtl::plus<pegtl::sor<pegtl::range<'a', 'z'>, pegtl::range<'A', 'Z'>,
283 pegtl::digit, pegtl::one<'.'>, pegtl::one<'-'>,
284 pegtl::one<'@'>, pegtl::one<'<'>, pegtl::one<'>'>,
288 template <
typename Input>
289 static void apply(
const Input &in,
Object &obj) {
290 std::string val = in.string();
292 if (obj.fieldType == FieldValuesType::INSTRUCTOR) {
293 for (
unsigned i = 0; i < obj.timetabler->
data.
instructors.size(); i++) {
296 obj.instructorValues.push_back(i);
301 LOG(ERROR) <<
"Instructor " << val <<
" does not exist.";
304 }
else if (obj.fieldType == FieldValuesType::COURSE) {
305 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
306 if (obj.timetabler->
data.
courses[i].getName() == val) {
308 obj.courseValues.push_back(i);
313 LOG(ERROR) <<
"Course " << val <<
" does not exist.";
316 }
else if (obj.fieldType == FieldValuesType::SEGMENT) {
317 for (
unsigned i = 0; i < obj.timetabler->
data.
segments.size(); i++) {
318 if (obj.timetabler->
data.
segments[i].getName() == val) {
320 obj.segmentValues.push_back(i);
325 LOG(ERROR) <<
"Segment " << val <<
" does not exist.";
328 }
else if (obj.fieldType == FieldValuesType::PROGRAM) {
329 for (
unsigned i = 0; i < obj.timetabler->
data.
programs.size(); i++) {
330 if (obj.timetabler->
data.
programs[i].getNameWithType() == val) {
332 obj.programValues.push_back(i);
337 LOG(ERROR) <<
"Program " << val <<
" does not exist.";
340 }
else if (obj.fieldType == FieldValuesType::ISMINOR) {
341 for (
unsigned i = 0; i < obj.timetabler->
data.
isMinors.size(); i++) {
342 if (obj.timetabler->
data.
isMinors[i].getName() == val) {
344 obj.isMinorValues.push_back(i);
349 LOG(ERROR) <<
"IsMinor " << val <<
" does not exist.";
352 }
else if (obj.fieldType == FieldValuesType::CLASSROOM) {
353 for (
unsigned i = 0; i < obj.timetabler->
data.
classrooms.size(); i++) {
356 obj.classValues.push_back(i);
361 LOG(ERROR) <<
"Classroom " << val <<
" does not exist.";
364 }
else if (obj.fieldType == FieldValuesType::SLOT) {
365 for (
unsigned i = 0; i < obj.timetabler->
data.
slots.size(); i++) {
366 if (obj.timetabler->
data.
slots[i].getName() == val) {
368 obj.slotValues.push_back(i);
373 LOG(ERROR) <<
"Slot " << val <<
" does not exist.";
383 struct allvalues : pegtl::pad<pegtl::one<'*'>, pegtl::space> {};
386 template <
typename Input>
387 static void apply(
const Input &in,
Object &obj) {
388 std::string val = in.string();
389 if (obj.fieldType == FieldValuesType::INSTRUCTOR) {
390 for (
unsigned i = 0; i < obj.timetabler->
data.
instructors.size(); i++) {
391 obj.instructorValues.push_back(i);
393 }
else if (obj.fieldType == FieldValuesType::COURSE) {
394 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
395 obj.courseValues.push_back(i);
397 }
else if (obj.fieldType == FieldValuesType::SEGMENT) {
398 for (
unsigned i = 0; i < obj.timetabler->
data.
segments.size(); i++) {
399 obj.segmentValues.push_back(i);
401 }
else if (obj.fieldType == FieldValuesType::PROGRAM) {
402 for (
unsigned i = 0; i < obj.timetabler->
data.
programs.size(); i++) {
403 obj.programValues.push_back(i);
405 }
else if (obj.fieldType == FieldValuesType::ISMINOR) {
406 for (
unsigned i = 0; i < obj.timetabler->
data.
isMinors.size(); i++) {
407 obj.isMinorValues.push_back(i);
409 }
else if (obj.fieldType == FieldValuesType::CLASSROOM) {
410 for (
unsigned i = 0; i < obj.timetabler->
data.
classrooms.size(); i++) {
411 obj.classValues.push_back(i);
413 }
else if (obj.fieldType == FieldValuesType::SLOT) {
414 for (
unsigned i = 0; i < obj.timetabler->
data.
slots.size(); i++) {
415 obj.slotValues.push_back(i);
425 struct sameval : pegtl::pad<TAO_PEGTL_KEYWORD("SAME"), pegtl::space> {};
428 template <
typename Input>
429 static void apply(
const Input &in,
Object &obj) {
430 if (obj.fieldType == FieldValuesType::CLASSROOM) {
431 obj.classSame =
true;
432 }
else if (obj.fieldType == FieldValuesType::SLOT) {
442 struct notsameval : pegtl::pad<TAO_PEGTL_KEYWORD("NOTSAME"), pegtl::space> {};
445 template <
typename Input>
446 static void apply(
const Input &in,
Object &obj) {
447 if (obj.fieldType == FieldValuesType::CLASSROOM) {
448 obj.classNotSame =
true;
449 }
else if (obj.fieldType == FieldValuesType::SLOT) {
450 obj.slotNotSame =
true;
459 : pegtl::seq<pegtl::pad<pegtl::one<'{'>, pegtl::space>,
460 pegtl::list<value, pegtl::one<','>, pegtl::space>,
461 pegtl::pad<pegtl::one<'}'>, pegtl::space>> {};
466 struct values : pegtl::sor<allvalues, listvalues, sameval, notsameval> {};
472 : pegtl::seq<pegtl::pad<classroomstr, pegtl::space>, values> {};
477 struct slotdecl : pegtl::seq<pegtl::pad<slotstr, pegtl::space>, values> {};
483 : pegtl::seq<pegtl::pad<coursestr, pegtl::space>, values> {};
486 template <
typename Input>
487 static void apply(
const Input &in,
Object &obj) {
488 obj.courseExcept =
false;
496 : pegtl::seq<pegtl::pad<coursestr, pegtl::space>,
497 pegtl::pad<exceptstr, pegtl::space>, values> {};
500 template <
typename Input>
501 static void apply(
const Input &in,
Object &obj) {
502 obj.courseExcept =
true;
509 struct coursedecl : pegtl::sor<coursenoexceptdecl, courseexceptdecl> {};
512 template <
typename Input>
513 static void apply(
const Input &in,
Object &obj) {
521 struct decl : pegtl::sor<slotdecl, classroomdecl> {};
526 struct decls : pegtl::list<decl, andstr, pegtl::space> {};
531 struct fielddecl : pegtl::seq<pegtl::pad<fieldtype, pegtl::space>, values> {};
536 struct fielddecls : pegtl::opt<pegtl::list<fielddecl, andstr, pegtl::space>> {};
542 : pegtl::seq<coursedecl, pegtl::pad<unbundlestr, pegtl::space>, fielddecls,
543 pegtl::opt<notstr>, pegtl::pad<instr, pegtl::space>, decl,
544 pegtl::pad<weightstr, pegtl::space>,
545 pegtl::pad<integer, pegtl::space>> {};
548 template <
typename Input>
549 static void apply(
const Input &in,
Object &obj) {
550 if (obj.courseExcept) {
551 std::vector<int> courseVals;
552 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
553 if (std::find(obj.courseValues.begin(), obj.courseValues.end(), i) ==
554 obj.courseValues.end()) {
555 courseVals.push_back(i);
558 obj.courseValues = courseVals;
560 for (
unsigned i = 0; i < obj.courseValues.size(); i++) {
561 int course = obj.courseValues[i];
563 ante = makeAntecedent(obj, course);
564 cons = makeConsequent(obj, course, i);
568 clause = ante >> cons;
569 obj.constraint = clause;
571 obj.timetabler->
newVar());
573 if (obj.integer != 0) {
577 obj.timetabler->
addClauses(hardConsequent, -1);
582 obj.courseValues.clear();
583 obj.instructorValues.clear();
584 obj.isMinorValues.clear();
585 obj.programValues.clear();
586 obj.segmentValues.clear();
587 obj.classValues.clear();
588 obj.slotValues.clear();
590 obj.classSame =
false;
591 obj.slotSame =
false;
592 obj.classNotSame =
false;
593 obj.slotNotSame =
false;
601 : pegtl::seq<coursedecl, pegtl::pad<bundlestr, pegtl::space>, fielddecls,
602 pegtl::opt<notstr>, pegtl::pad<instr, pegtl::space>, decl,
603 pegtl::pad<weightstr, pegtl::space>,
604 pegtl::pad<integer, pegtl::space>> {};
607 template <
typename Input>
608 static void apply(
const Input &in,
Object &obj) {
610 if (obj.courseExcept) {
611 std::vector<int> courseVals;
612 for (
unsigned i = 0; i < obj.timetabler->
data.
courses.size(); i++) {
613 if (std::find(obj.courseValues.begin(), obj.courseValues.end(), i) ==
614 obj.courseValues.end()) {
615 courseVals.push_back(i);
618 obj.courseValues = courseVals;
620 for (
unsigned i = 0; i < obj.courseValues.size(); i++) {
621 int course = obj.courseValues[i];
623 ante = makeAntecedent(obj, course);
624 cons = makeConsequent(obj, course, i);
628 clause = ante >> cons;
629 clauses = clauses & clause;
632 obj.constraint = clauses;
635 obj.timetabler->
newVar());
637 if (obj.integer != 0) {
641 obj.timetabler->
addClauses(hardConsequent, -1);
645 obj.courseValues.clear();
646 obj.instructorValues.clear();
647 obj.isMinorValues.clear();
648 obj.programValues.clear();
649 obj.segmentValues.clear();
650 obj.classValues.clear();
651 obj.slotValues.clear();
653 obj.classSame =
false;
654 obj.slotSame =
false;
655 obj.classNotSame =
false;
656 obj.slotNotSame =
false;
665 pegtl::must<pegtl::star<pegtl::sor<constraint_bundle, constraint_unbundle>>,
668 template <
typename Rule>
670 template <
typename Input,
typename... States>
671 static void raise(
const Input &in, States &&...) {
672 LOG(ERROR) << in.position() <<
" Error parsing custom constraints";
690 obj.constraintEncoder = constraintEncoder;
692 pegtl::file_input<> in(file);
705 classNotSame =
false;
Parse "NOTSAME": Used to specify constraints on courses with different field values.
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 * 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.
Parse a constraint with bundle keyword.
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...
Class for representing a set of clauses.
Parse "ISMNOR": Similar to classroom.
Parse fieldd decl in antecedent of the 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.