Something went wrong. Try again.
A functional toolkit for authoring resource-leveling algorithms — compose constraint and scoring blocks, enumerate feasible schedules
Something went wrong. Try again.
2.2 kB · 58 lines
TypeScript
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859// MaxConcurrentResource — Constraint block.//// Caps the number of *tasks* that may simultaneously demand a named// resource on any working day. Counts tasks (boolean activity), not// fractional unit demand — the unit-summing variant is `PeakCap`. The// greedy serial-SGS and the MiniZinc fragment both use task-count// semantics so the two backends agree on part-time assignments.//// MiniZinc target shape (matches the shared compile contract): `active[t,d]`// is the boolean activity matrix, `tasks_demanding[r]` the index set of// tasks demanding resource `r`, and `DAYS` the day-index set — all// supplied by the compilation harness, not the block.
import { z } from "zod";
import type { MaxConcurrentResourceConstraint } from "../level-core/types.ts";
import type { ConstraintBlock, MiniZincFragment } from "./types.ts";
export const MaxConcurrentResourceInputSchema = z.object({ resourceUniqueId: z.number().int(), max: z.number().int().positive(),});
export type MaxConcurrentResourceInput = z.infer< typeof MaxConcurrentResourceInputSchema>;
const MaxConcurrentResourceOutputSchema: z.ZodType<MaxConcurrentResourceConstraint> = z.object({ kind: z.literal("MaxConcurrentResource"), resourceUniqueId: z.number().int(), max: z.number().int().positive(), });
export const MaxConcurrentResourceBlock: ConstraintBlock<MaxConcurrentResourceInput> = { id: "MaxConcurrentResource", schema: { input: MaxConcurrentResourceInputSchema, output: MaxConcurrentResourceOutputSchema, }, apply: ({ resourceUniqueId, max }): MaxConcurrentResourceConstraint => ({ kind: "MaxConcurrentResource", resourceUniqueId, max, }), toMiniZinc: ({ resourceUniqueId, max }): MiniZincFragment => ({ text: `constraint forall(d in DAYS) ` + `( sum(t in tasks_demanding[${String(resourceUniqueId)}]) ` + `(bool2int(active[t,d])) <= ${String(max)} );`, }), doc: { nl: "At most N tasks may simultaneously demand the named resource on any working day.", pseudocode: "forall day d: count(t demanding r and active(t,d)) <= max", }, };