Skip to content

Commit

Permalink
speed up with necessary courses
Browse files Browse the repository at this point in the history
  • Loading branch information
KobeZ123 committed Jan 31, 2025
1 parent 6c475bc commit 505fe56
Showing 1 changed file with 68 additions and 0 deletions.
68 changes: 68 additions & 0 deletions packages/common/src/major2-validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,19 @@ interface CourseValidationTracker {

// do we have enough courses to take all classes in both solutions?
hasEnoughCoursesForBoth(s1: Solution, s2: Solution): boolean;

setNecessaryCourses(courses: Set<string>): void;

getNecessaryCourses(): Set<string>;
}

// exported for testing
export class Major2ValidationTracker implements CourseValidationTracker {
// maps courseString => [course instance, # of times taken]
private currentCourses: Map<string, [ScheduleCourse2<unknown>, number]>;

private necessaryCourses: Set<string> = new Set();

constructor(courses: ScheduleCourse2<unknown>[]) {
this.currentCourses = new Map();
for (const c of courses) {
Expand Down Expand Up @@ -260,6 +266,14 @@ export class Major2ValidationTracker implements CourseValidationTracker {
return true;
}

setNecessaryCourses(courses: Set<string>) {
this.necessaryCourses = courses;
}

getNecessaryCourses() {
return this.necessaryCourses;
}

// Maps the # of each course required in the given solution
private static createTakenMap(s: Solution): Map<string, number> {
const map = new Map();
Expand Down Expand Up @@ -295,6 +309,10 @@ export function validateMajor2(
}

const majorReqs = [...major.requirementSections, ...concentrationReq];

const requiredCourses: Set<string> = new Set();
tracker.setNecessaryCourses(getNecessaryCourses(majorReqs, requiredCourses));

// create a big AND requirement of all the sections and selected concentrations
const requirementsResult = validateRequirement(
{
Expand Down Expand Up @@ -323,6 +341,52 @@ export function validateMajor2(
});
}

/**
* Crawls through the requirements, producing a list of necessary courses. This
* is used to filter out courses that cannot be used for the range.
*/
export function getNecessaryCourses(
requirements: Requirement2[],
requiredCourses: Set<string>
): Set<string> {
const tracker = new Major2ValidationTracker([]);

for (const req of requirements) {
crawlRequirement(req, tracker, requiredCourses);
}
console.log("KOBE");
console.log(requiredCourses);
return requiredCourses;
}

/** Crawls through the requirements, producing a list of necessary courses. */
function crawlRequirement(
req: Requirement2,
tracker: CourseValidationTracker,
requiredCourses: Set<string>
): void {
switch (req.type) {
// base cases
case "COURSE":
requiredCourses.add(courseToString(req));
break;
// inductive cases
case "AND":
req.courses.forEach((r) => crawlRequirement(r, tracker, requiredCourses));
break;
case "SECTION":
req.requirements.forEach((r) =>
crawlRequirement(r, tracker, requiredCourses)
);
case "XOM":
case "OR":
case "RANGE":
break;
default:
return assertUnreachable(req);
}
}

/**
* Produces the selected input concentrations to be included in major validation.
*
Expand Down Expand Up @@ -443,6 +507,9 @@ function validateRangeRequirement(
): Result<Array<Solution>, MajorValidationError> {
// get the eligible courses (Filter out exceptions)
const exceptions = new Set(r.exceptions.map(courseToString));
console.log("necessaryCourses", tracker.getNecessaryCourses());
tracker.getNecessaryCourses().forEach((course) => exceptions.add(course));

const courses = tracker
.getAll(r.subject, r.idRangeStart, r.idRangeEnd)
.filter((c) => !exceptions.has(courseToString(c)));
Expand Down Expand Up @@ -473,6 +540,7 @@ function validateRangeRequirement(
solutionsSoFarWithCourse.push(courseSol);
solutionsSoFar.push(...solutionsSoFarWithCourse);
}
console.log("Solutions so far", solutionsSoFar);
return Ok(solutionsSoFar);
}

Expand Down

0 comments on commit 505fe56

Please sign in to comment.