Skip to content

Optimize schedule generation and improve optional course handling#446

Open
YasushikoX wants to merge 3 commits into
sandboxnu:mainfrom
YasushikoX:sceduler-improvements
Open

Optimize schedule generation and improve optional course handling#446
YasushikoX wants to merge 3 commits into
sandboxnu:mainfrom
YasushikoX:sceduler-improvements

Conversation

@YasushikoX
Copy link
Copy Markdown

Optimize schedule generation algorithm

Yes, the branch is called sceduler-improvements. Yes it is missing h.

This PR optimizes the core algorithm, adds a result cap, and rewrites the test suite.

Algorithm changes

  1. Range-mask formula in binaryMeetingTime.ts - Replaced per-slot bit loop with (1n << numSlots) - 1n shifted into place. One expression instead of a tight loop.

  2. Prefix mask array in generateCombinations.ts - Instead of rechecking the whole schedule from scratch each iteration, a prefixMasks array maintains the running OR of all accepted masks. Conflict detection goes from O(n) to O(1) per position, and the prefix state is reused when only the last index advances.

  3. Precomputed optional masks in generateSchedules.ts - Optional section masks are computed once before the main loop instead of once per locked schedule. addOptionalCourses threads a single combined bigint mask through recursion instead of an array, and uses push/pop instead of array spreading.

  4. MAX_RESULTS cap (100) - Prevents runaway generation when many non-conflicting sections exist. This was the primary cause of the hour-long runtime.

Bug fixes

  1. Empty course guard - Added early return when any course has zero sections. Previously this would silently produce wrong results.

  2. Single-course maxResults - The single-course fast path now respects the maxResults cap via .slice(). Previously it was ignored.

Test improvements

  1. Rewrote generateSchedules.test.ts - The old tests tested local shadow copies of the logic, not the actual production functions. The new file imports and tests the real implementations. Covers locked-only, optional-only, mixed, numCourses edge cases, MAX_RESULTS capping, and conflict invariants.

  2. New addOptionalCourses.test.ts - Full coverage for the new function: skip/include choices, conflict filtering, multi-meeting sections, numCourses combinations, maxResults capping, and push/pop array isolation safety.

  3. New unit tests in binaryMeetingTime.test.ts - New tests covering incrementIndex carry/overflow, meetingTimesToBinaryMask edge cases (zero-duration, multi-day, multi-block, back-to-back), masksConflict, and generateCombinationsOptimized (empty course guard, mask correctness, single-course cap).

  4. Benchmark suite - Before/after comparison across 13 scenarios including adversarial, edge case, and uncapped exhaustion tests. File is named benchmark.bench.ts (not .test.ts) so it won't run during normal CI test runs. Run manually with npx tsx --test apps/searchneu/lib/scheduler/binaryMeetingTimeTests/benchmark.bench.ts.

Benchmark results (69 unit tests + 21 benchmarks, all passing)

┌─ small  (4 × 8,    4,096 brute force)
│  original :           100 results         0.3 ms
│  optimized:           100 results         0.2 ms   (1.2x faster)
└────────────────────────────────────────────────────────────

┌─ medium (6 × 10,  1,000,000 brute force)
│  original :           100 results         0.8 ms
│  optimized:           100 results         0.5 ms   (1.6x faster)
└────────────────────────────────────────────────────────────

┌─ large  (8 × 12,  429,981,696 brute force)
│  original :           100 results         1.3 ms
│  optimized:           100 results         0.2 ms   (6.6x faster)
└────────────────────────────────────────────────────────────

┌─ massive (10 × 15, 576,650,390,625 brute force)
│  original :           100 results         4.9 ms
│  optimized:           100 results         0.1 ms   (37.5x faster)
└────────────────────────────────────────────────────────────

┌─ deep   (12 × 10, 1e12 brute force - overconstrained)
│  original :             0 results      4936.9 ms
│  optimized:             0 results       141.4 ms   (34.9x faster)
└────────────────────────────────────────────────────────────

┌─ uncapped (8 × 12, no cap - full exhaustion)
│  original :       2419200 results      8575.8 ms
│  optimized:       2419200 results      1560.1 ms   (5.5x faster)
└────────────────────────────────────────────────────────────

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
searchneu Error Error Apr 8, 2026 9:08pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
searchneu-docs Skipped Skipped Apr 8, 2026 9:08pm

Request Review

@vercel vercel Bot temporarily deployed to Preview – searchneu-docs April 8, 2026 20:25 Inactive
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 8, 2026

@YasushikoX is attempting to deploy a commit to the Sandbox NU Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors and optimizes the scheduler’s core schedule-generation logic by introducing a more efficient combination generator, improving optional-course handling, and expanding the unit test suite to cover the production implementations.

Changes:

  • Introduces generateCombinationsOptimized + addOptionalCourses helpers (with MAX_RESULTS) and wires them into generateSchedules.
  • Optimizes meeting-time mask creation in binaryMeetingTime.ts using a range-mask formula.
  • Replaces prior “shadow implementation” tests with end-to-end tests against the real scheduling functions; adds optional-course and benchmark coverage.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
package-lock.json Adds an npm lockfile (new) alongside existing pnpm setup.
apps/searchneu/lib/scheduler/generateSchedules.ts Switches schedule generation to new optimized helpers; precomputes optional masks; applies MAX_RESULTS when adding optionals.
apps/searchneu/lib/scheduler/generateSchedules.test.ts Rewrites tests to exercise production scheduling helpers via a DB-free simulation.
apps/searchneu/lib/scheduler/generateCombinations.ts New optimized locked-combination generator (prefix masks) and optimized optional-course recursion with caps.
apps/searchneu/lib/scheduler/binaryMeetingTimeTests/binaryMeetingTime.test.ts Adds coverage for mask encoding, incrementIndex, masksConflict, and combination edge cases.
apps/searchneu/lib/scheduler/binaryMeetingTimeTests/addOptionalCourses.test.ts New comprehensive test suite for optional-course expansion logic.
apps/searchneu/lib/scheduler/binaryMeetingTimeTests/benchmark.bench.ts Adds manual benchmark suite for before/after comparisons.
apps/searchneu/lib/scheduler/binaryMeetingTime.ts Replaces per-slot bit setting with a contiguous range-mask shift.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/searchneu/lib/scheduler/generateSchedules.ts
@mehallhm mehallhm added the area:scheduler issue related to the scheduler label Apr 8, 2026
@YasushikoX
Copy link
Copy Markdown
Author

benchmark.bench.ts exists purely to compare the old vs new algorithm side by side. It bundles a copy of the original code for that purpose. This file can be removed entirely since it has no value in production or ongoing CI.

Replace per-slot looping with a BigInt range-mask in meetingTimesToBinaryMask for faster mask construction and remove the now-unused helper. Introduce generateCombinations.ts: an optimized, iterative combination generator with prefix/skip logic and a MAX_RESULTS cap to avoid runaway generation. Update generateSchedules to use the new generator, precompute optional section masks, and rewrite addOptionalCourses to thread a combined bigint mask and respect MAX_RESULTS for early exit. Add extensive unit/benchmark tests to validate performance and correctness across many scenarios.
Introduce addOptionalCourses to generate valid combinations including optional courses and export it from generateCombinations.ts. Reduce MAX_RESULTS from 1_000 to 100 and add guards/limits in generateCombinationsOptimized (single-course slicing and empty-course early-return) to avoid runaway generation. Add extensive unit tests: new addOptionalCourses tests, expanded binaryMeetingTime tests (meetingTimesToBinaryMask, masksConflict, incrementIndex) and updated generateSchedules tests to exercise the locked+optional pipeline. These changes improve correctness for optional course handling and strengthen test coverage.
@YasushikoX YasushikoX force-pushed the sceduler-improvements branch from 0f4927d to 8f88c96 Compare April 8, 2026 21:02
@vercel vercel Bot temporarily deployed to Preview – searchneu-docs April 8, 2026 21:02 Inactive
Rename benchmark.test.ts to benchmark.bench.ts and move the large benchmarking suite and helper builders (scaling, adversarial, realistic, edge cases) into the new .bench file. Trim binaryMeetingTime.test.ts to keep unit tests (remove the long benchmark helpers and brute-force generator/original comparisons), and update imports accordingly. Also remove the re-export of incrementIndex from generateSchedules.ts to avoid exposing that internal helper.
@YasushikoX YasushikoX force-pushed the sceduler-improvements branch from 8f88c96 to 8cc1b5d Compare April 8, 2026 21:08
@vercel vercel Bot temporarily deployed to Preview – searchneu-docs April 8, 2026 21:08 Inactive
@ArmaanMehra
Copy link
Copy Markdown
Contributor

ArmaanMehra commented Apr 9, 2026

Hey, really appreciate you taking the time to dig into the codebase and put this together! External contributions mean a lot to us and this is genuinely impressive work.

We do have a more pressing change to the generation algorithm that we need to get merged first before we can bring this in, to avoid conflicts. Once that's in we'll do a proper review of this PR and work with you to get it merged. Don't want this to get lost; we'll make sure it doesn't.

Thanks again, this is exactly the kind of contribution that makes open source great! 🙏

@YasushikoX
Copy link
Copy Markdown
Author

Hello, no worries, if you could comment whenever those changes would be merged in I will be happy to bring my branch up to date and revise any changes in case there would be conflicts.

Happy to help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:scheduler issue related to the scheduler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants