@bike4mind/cli 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BackgroundAgentManager-ChmoEU9H.mjs → BackgroundAgentManager-BEPNKfmi.mjs} +2574 -190
- package/dist/{ConfigStore-yJU1dxpP.mjs → ConfigStore-BbTg-UaE.mjs} +134 -2
- package/dist/commands/apiCommand.mjs +1 -1
- package/dist/commands/doctorCommand.mjs +1 -1
- package/dist/commands/envCommand.mjs +1 -1
- package/dist/commands/headlessCommand.mjs +2 -2
- package/dist/commands/mcpCommand.mjs +1 -1
- package/dist/commands/updateCommand.mjs +1 -1
- package/dist/index.mjs +3 -3
- package/dist/{package-B3f78bSl.mjs → package-CSa_ad8r.mjs} +1 -1
- package/package.json +8 -8
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as PermissionDeniedError, $t as extractSnippetMeta, A as FriendshipEvents, At as XAI_IMAGE_MODELS, B as InboxEvents, Bt as isZodError, C as CorruptedFileError, Ct as TransferCreditTransaction, D as FeedbackEvents, Dt as VIDEO_SIZE_CONSTRAINTS, E as FavoriteDocumentType, Et as UnprocessableEntityError, F as HTTPError, Ft as getViewById, G as LLMEvents, Gt as sanitizeTelemetryError, H as InviteEvents, Ht as obfuscateApiKey, I as HttpStatus, It as isGPTImage2Model, J as ModelBackend, Jt as substituteArguments$1, K as MiscEvents, Kt as secureParameters, L as ImageEditUsageTransaction, Lt as isGPTImageModel, M as GenerateImageToolCallSchema, Mt as dayjsConfig_default, N as GenericCreditAddTransaction, Nt as getAccessibleDataLakes, O as FileEvents, Ot as VideoGenerationUsageTransaction, P as GenericCreditDeductTransaction, Pt as getMcpProviderMetadata, Q as Permission, Qt as buildRateLimitLogEntry, R as ImageGenerationUsageTransaction, Rt as isModelAccessible, S as CompletionApiUsageTransaction, St as ToolUsageTransaction, T as ElabsEvents, Tt as UnauthorizedError, U as InviteType, Ut as parseSkillArguments, V as InternalServerError, Vt as mapMimeTypeToArtifactType, W as KnowledgeType, Wt as resolveNavigationIntents, X as OpenAIEmbeddingModel, Y as NotFoundError, Yt as toDataLakeConfig, Z as OpenAIImageGenerationInput, _ as BadRequestError, _t as SupportedFabFileMimeTypes, at as QuestMasterParamsSchema, b as ChatModels, bt as TextGenerationUsageTransaction, c as AiEvents, ct as RechartsChartTypeList, d as ApiKeyType, dt as ResearchTaskExecutionType, en as isNearLimit, et as ProfileEvents, f as AppFileEvents, ft as ResearchTaskPeriodicFrequencyType, g as BFL_SAFETY_TOLERANCE, gt as SubscriptionCreditTransaction, h as BFL_IMAGE_MODELS, ht as SpeechToTextUsageTransaction, it as PurchaseTransaction, j as GEMINI_IMAGE_MODELS, jt as b4mLLMTools, k as ForbiddenError, kt as VideoModels, l as ApiKeyEvents, lt as RegInviteEvents, m as AuthEvents, mt as SessionEvents, n as logger, nn as CollectionType, nt as PromptIntentSchema, ot as RealtimeVoiceUsageTransaction, p as ArtifactTypeSchema, pt as ResearchTaskType, q as ModalEvents, qt as settingsMap, rt as PromptMetaZodSchema, s as ALERT_THRESHOLDS, st as ReceivedCreditTransaction, t as ConfigStore, tn as parseRateLimitHeaders, tt as ProjectEvents, u as ApiKeyScope, ut as ResearchModeParamsSchema, vt as TagType, w as DashboardParamsSchema, wt as UiNavigationEvents, x as ClaudeArtifactMimeTypes, xt as TooManyRequestsError, y as ChatCompletionCreateInputSchema, yt as TaskScheduleHandler, z as ImageModels, zt as isSupportedEmbeddingModel } from "./ConfigStore-
|
|
2
|
+
import { $ as PermissionDeniedError, $t as extractSnippetMeta, A as FriendshipEvents, At as XAI_IMAGE_MODELS, B as InboxEvents, Bt as isZodError, C as CorruptedFileError, Ct as TransferCreditTransaction, D as FeedbackEvents, Dt as VIDEO_SIZE_CONSTRAINTS, E as FavoriteDocumentType, Et as UnprocessableEntityError, F as HTTPError, Ft as getViewById, G as LLMEvents, Gt as sanitizeTelemetryError, H as InviteEvents, Ht as obfuscateApiKey, I as HttpStatus, It as isGPTImage2Model, J as ModelBackend, Jt as substituteArguments$1, K as MiscEvents, Kt as secureParameters, L as ImageEditUsageTransaction, Lt as isGPTImageModel, M as GenerateImageToolCallSchema, Mt as dayjsConfig_default, N as GenericCreditAddTransaction, Nt as getAccessibleDataLakes, O as FileEvents, Ot as VideoGenerationUsageTransaction, P as GenericCreditDeductTransaction, Pt as getMcpProviderMetadata, Q as Permission, Qt as buildRateLimitLogEntry, R as ImageGenerationUsageTransaction, Rt as isModelAccessible, S as CompletionApiUsageTransaction, St as ToolUsageTransaction, T as ElabsEvents, Tt as UnauthorizedError, U as InviteType, Ut as parseSkillArguments, V as InternalServerError, Vt as mapMimeTypeToArtifactType, W as KnowledgeType, Wt as resolveNavigationIntents, X as OpenAIEmbeddingModel, Y as NotFoundError, Yt as toDataLakeConfig, Z as OpenAIImageGenerationInput, _ as BadRequestError, _t as SupportedFabFileMimeTypes, at as QuestMasterParamsSchema, b as ChatModels, bt as TextGenerationUsageTransaction, c as AiEvents, ct as RechartsChartTypeList, d as ApiKeyType, dt as ResearchTaskExecutionType, en as isNearLimit, et as ProfileEvents, f as AppFileEvents, ft as ResearchTaskPeriodicFrequencyType, g as BFL_SAFETY_TOLERANCE, gt as SubscriptionCreditTransaction, h as BFL_IMAGE_MODELS, ht as SpeechToTextUsageTransaction, it as PurchaseTransaction, j as GEMINI_IMAGE_MODELS, jt as b4mLLMTools, k as ForbiddenError, kt as VideoModels, l as ApiKeyEvents, lt as RegInviteEvents, m as AuthEvents, mt as SessionEvents, n as logger, nn as CollectionType, nt as PromptIntentSchema, ot as RealtimeVoiceUsageTransaction, p as ArtifactTypeSchema, pt as ResearchTaskType, q as ModalEvents, qt as settingsMap, rt as PromptMetaZodSchema, s as ALERT_THRESHOLDS, st as ReceivedCreditTransaction, t as ConfigStore, tn as parseRateLimitHeaders, tt as ProjectEvents, u as ApiKeyScope, ut as ResearchModeParamsSchema, vt as TagType, w as DashboardParamsSchema, wt as UiNavigationEvents, x as ClaudeArtifactMimeTypes, xt as TooManyRequestsError, y as ChatCompletionCreateInputSchema, yt as TaskScheduleHandler, z as ImageModels, zt as isSupportedEmbeddingModel } from "./ConfigStore-BbTg-UaE.mjs";
|
|
3
3
|
import { a as isUserLockedOut, c as userCanDisableMFA, d as userRequiresMFA, f as verifyBackupCode, i as getLockoutTimeRemaining, l as userEligibleForMFA, n as generateBackupCodes, o as recordFailedAttempt, p as verifyTOTPToken, r as generateTOTPSetup, s as shouldResetFailedAttempts, t as clearFailedAttempts, u as userHasMFAConfigured } from "./utils-fqhJmuB8.mjs";
|
|
4
4
|
import { n as isPathAllowed, t as assertPathAllowed } from "./pathValidation-D8tjkQXE-1HwvsuYT.mjs";
|
|
5
|
-
import { t as version } from "./package-
|
|
5
|
+
import { t as version } from "./package-CSa_ad8r.mjs";
|
|
6
6
|
import { execFile, execFileSync, spawn } from "child_process";
|
|
7
7
|
import crypto, { createHash, randomBytes, randomUUID } from "crypto";
|
|
8
8
|
import { existsSync, promises, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "fs";
|
|
@@ -8876,22 +8876,22 @@ function makeSchedulingResult(args) {
|
|
|
8876
8876
|
const OperationSchema = z.object({
|
|
8877
8877
|
jobId: z.number(),
|
|
8878
8878
|
machineId: z.number(),
|
|
8879
|
-
duration: z.number().positive()
|
|
8879
|
+
duration: z.number().positive().max(1e6)
|
|
8880
8880
|
});
|
|
8881
8881
|
const JobSchema = z.object({
|
|
8882
8882
|
id: z.number(),
|
|
8883
|
-
name: z.string(),
|
|
8884
|
-
operations: z.array(OperationSchema)
|
|
8883
|
+
name: z.string().max(200),
|
|
8884
|
+
operations: z.array(OperationSchema).max(1e3)
|
|
8885
8885
|
});
|
|
8886
8886
|
const MachineSchema = z.object({
|
|
8887
8887
|
id: z.number(),
|
|
8888
|
-
name: z.string()
|
|
8888
|
+
name: z.string().max(200)
|
|
8889
8889
|
});
|
|
8890
8890
|
const SchedulingProblemSchema = z.object({
|
|
8891
|
-
name: z.string(),
|
|
8892
|
-
description: z.string().optional(),
|
|
8893
|
-
jobs: z.array(JobSchema),
|
|
8894
|
-
machines: z.array(MachineSchema),
|
|
8891
|
+
name: z.string().max(200),
|
|
8892
|
+
description: z.string().max(2e3).optional(),
|
|
8893
|
+
jobs: z.array(JobSchema).max(1e3),
|
|
8894
|
+
machines: z.array(MachineSchema).max(1e3),
|
|
8895
8895
|
solvedJobUrl: z.string().url().optional()
|
|
8896
8896
|
});
|
|
8897
8897
|
const SolverIdSchema = z.enum([
|
|
@@ -8955,13 +8955,18 @@ const greedySolver = {
|
|
|
8955
8955
|
totalIterations: totalOps
|
|
8956
8956
|
});
|
|
8957
8957
|
}
|
|
8958
|
+
const makespan = Math.max(...schedule.map((op) => op.endTime));
|
|
8958
8959
|
return makeSchedulingResult({
|
|
8959
8960
|
solverId: "greedy",
|
|
8960
8961
|
solverName: "Greedy (Earliest Start)",
|
|
8961
|
-
makespan
|
|
8962
|
+
makespan,
|
|
8962
8963
|
schedule,
|
|
8963
8964
|
elapsedMs: performance.now() - startTime,
|
|
8964
|
-
iterations: totalOps
|
|
8965
|
+
iterations: totalOps,
|
|
8966
|
+
trace: [{
|
|
8967
|
+
solution: schedule,
|
|
8968
|
+
objective: makespan
|
|
8969
|
+
}]
|
|
8965
8970
|
});
|
|
8966
8971
|
}
|
|
8967
8972
|
};
|
|
@@ -9092,6 +9097,34 @@ function validateScheduleFeasibility(schedule) {
|
|
|
9092
9097
|
return true;
|
|
9093
9098
|
}
|
|
9094
9099
|
/**
|
|
9100
|
+
* Append a best-so-far snapshot, thinning the early history when over cap so the
|
|
9101
|
+
* trace stays bounded while preserving the first point and recent progress.
|
|
9102
|
+
* (Same thinning policy as the family engine's pushTrace.)
|
|
9103
|
+
*/
|
|
9104
|
+
function pushScheduleTrace(trace, schedule, makespan) {
|
|
9105
|
+
trace.push({
|
|
9106
|
+
solution: schedule,
|
|
9107
|
+
objective: makespan
|
|
9108
|
+
});
|
|
9109
|
+
if (trace.length > 48) {
|
|
9110
|
+
const first = trace[0];
|
|
9111
|
+
const rest = trace.slice(1).filter((_, i) => i % 2 === 1);
|
|
9112
|
+
trace.length = 0;
|
|
9113
|
+
trace.push(first, ...rest);
|
|
9114
|
+
}
|
|
9115
|
+
}
|
|
9116
|
+
const nowMs = () => typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
9117
|
+
/**
|
|
9118
|
+
* Combine the timeoutMs budget with cooperative cancellation into one stop check
|
|
9119
|
+
* that iterative solvers poll between moves — so a UI cancel or a timeout actually
|
|
9120
|
+
* halts a long run instead of being decorative. `defaultTimeoutMs` preserves each
|
|
9121
|
+
* solver's historical default when the caller omits timeoutMs.
|
|
9122
|
+
*/
|
|
9123
|
+
function makeScheduleStopper(options, startTime, defaultTimeoutMs) {
|
|
9124
|
+
const deadline = startTime + (options?.timeoutMs ?? defaultTimeoutMs);
|
|
9125
|
+
return () => (options?.shouldCancel?.() ?? false) || nowMs() > deadline;
|
|
9126
|
+
}
|
|
9127
|
+
/**
|
|
9095
9128
|
* Simple seeded pseudo-random number generator (mulberry32).
|
|
9096
9129
|
*/
|
|
9097
9130
|
function createRng$1(seed) {
|
|
@@ -9127,19 +9160,25 @@ const naiveSolver = {
|
|
|
9127
9160
|
description: "Evaluates all permutations to find the optimal schedule. Only feasible for small problems.",
|
|
9128
9161
|
async solve(problem, options) {
|
|
9129
9162
|
const startTime = performance.now();
|
|
9163
|
+
const stop = makeScheduleStopper(options, startTime, 15e3);
|
|
9130
9164
|
const ops = buildOperationList(problem);
|
|
9131
9165
|
const totalPerms = factorial(ops.length);
|
|
9132
9166
|
const cappedTotal = Math.min(totalPerms, MAX_PERMUTATIONS);
|
|
9133
|
-
let bestMakespan = Infinity;
|
|
9134
9167
|
let bestSchedule = decodePermutation(ops, problem);
|
|
9168
|
+
let bestMakespan = computeMakespan(bestSchedule);
|
|
9135
9169
|
let count = 0;
|
|
9170
|
+
const trace = [{
|
|
9171
|
+
solution: bestSchedule,
|
|
9172
|
+
objective: bestMakespan
|
|
9173
|
+
}];
|
|
9136
9174
|
for (const perm of permutations(ops)) {
|
|
9137
|
-
if (count >= MAX_PERMUTATIONS) break;
|
|
9175
|
+
if (count >= MAX_PERMUTATIONS || stop()) break;
|
|
9138
9176
|
const schedule = decodePermutation(perm, problem);
|
|
9139
9177
|
const makespan = computeMakespan(schedule);
|
|
9140
9178
|
if (makespan < bestMakespan) {
|
|
9141
9179
|
bestMakespan = makespan;
|
|
9142
9180
|
bestSchedule = schedule;
|
|
9181
|
+
pushScheduleTrace(trace, bestSchedule, bestMakespan);
|
|
9143
9182
|
}
|
|
9144
9183
|
count++;
|
|
9145
9184
|
if (options?.onProgress && count % 100 === 0) options.onProgress({
|
|
@@ -9163,7 +9202,8 @@ const naiveSolver = {
|
|
|
9163
9202
|
makespan: bestMakespan,
|
|
9164
9203
|
schedule: bestSchedule,
|
|
9165
9204
|
elapsedMs: performance.now() - startTime,
|
|
9166
|
-
iterations: count
|
|
9205
|
+
iterations: count,
|
|
9206
|
+
trace
|
|
9167
9207
|
});
|
|
9168
9208
|
}
|
|
9169
9209
|
};
|
|
@@ -9188,18 +9228,22 @@ const randomRestartSolver = {
|
|
|
9188
9228
|
description: "Multiple random starts with local search improvement via operation swaps.",
|
|
9189
9229
|
async solve(problem, options) {
|
|
9190
9230
|
const startTime = performance.now();
|
|
9191
|
-
const
|
|
9231
|
+
const stop = makeScheduleStopper(options, startTime, 1e4);
|
|
9192
9232
|
const rng = createRng$1(42);
|
|
9193
|
-
let globalBestMakespan = Infinity;
|
|
9194
9233
|
let globalBestSchedule = decodePermutation(randomPermutation(problem, rng), problem);
|
|
9234
|
+
let globalBestMakespan = computeMakespan(globalBestSchedule);
|
|
9195
9235
|
let totalIterations = 0;
|
|
9236
|
+
const trace = [{
|
|
9237
|
+
solution: globalBestSchedule,
|
|
9238
|
+
objective: globalBestMakespan
|
|
9239
|
+
}];
|
|
9196
9240
|
for (let restart = 0; restart < RESTARTS; restart++) {
|
|
9197
|
-
if (
|
|
9241
|
+
if (stop()) break;
|
|
9198
9242
|
let currentPerm = randomPermutation(problem, rng);
|
|
9199
9243
|
let currentSchedule = decodePermutation(currentPerm, problem);
|
|
9200
9244
|
let currentMakespan = computeMakespan(currentSchedule);
|
|
9201
9245
|
for (let i = 0; i < HILL_CLIMB_ITERATIONS; i++) {
|
|
9202
|
-
if (
|
|
9246
|
+
if (stop()) break;
|
|
9203
9247
|
const neighborPerm = swapNeighbor(currentPerm, rng);
|
|
9204
9248
|
const neighborSchedule = decodePermutation(neighborPerm, problem);
|
|
9205
9249
|
const neighborMakespan = computeMakespan(neighborSchedule);
|
|
@@ -9213,6 +9257,7 @@ const randomRestartSolver = {
|
|
|
9213
9257
|
if (currentMakespan < globalBestMakespan) {
|
|
9214
9258
|
globalBestMakespan = currentMakespan;
|
|
9215
9259
|
globalBestSchedule = currentSchedule;
|
|
9260
|
+
pushScheduleTrace(trace, globalBestSchedule, globalBestMakespan);
|
|
9216
9261
|
}
|
|
9217
9262
|
options?.onProgress?.({
|
|
9218
9263
|
solverId: "random-restart",
|
|
@@ -9228,7 +9273,8 @@ const randomRestartSolver = {
|
|
|
9228
9273
|
makespan: globalBestMakespan,
|
|
9229
9274
|
schedule: globalBestSchedule,
|
|
9230
9275
|
elapsedMs: performance.now() - startTime,
|
|
9231
|
-
iterations: totalIterations
|
|
9276
|
+
iterations: totalIterations,
|
|
9277
|
+
trace
|
|
9232
9278
|
});
|
|
9233
9279
|
}
|
|
9234
9280
|
};
|
|
@@ -9265,17 +9311,21 @@ function createSASolver(config) {
|
|
|
9265
9311
|
description: config.description,
|
|
9266
9312
|
async solve(problem, options) {
|
|
9267
9313
|
const startTime = performance.now();
|
|
9268
|
-
const
|
|
9314
|
+
const stop = makeScheduleStopper(options, startTime, 3e4);
|
|
9269
9315
|
const rng = createRng$1(42);
|
|
9270
9316
|
let currentPerm = randomPermutation(problem, rng);
|
|
9271
9317
|
let currentSchedule = decodePermutation(currentPerm, problem);
|
|
9272
9318
|
let currentMakespan = computeMakespan(currentSchedule);
|
|
9273
9319
|
let bestSchedule = currentSchedule;
|
|
9274
9320
|
let bestMakespan = currentMakespan;
|
|
9321
|
+
const trace = [{
|
|
9322
|
+
solution: bestSchedule,
|
|
9323
|
+
objective: bestMakespan
|
|
9324
|
+
}];
|
|
9275
9325
|
let temperature = config.initialTemp;
|
|
9276
9326
|
const progressInterval = Math.max(1, Math.floor(config.iterations / 100));
|
|
9277
9327
|
for (let i = 0; i < config.iterations; i++) {
|
|
9278
|
-
if (
|
|
9328
|
+
if (stop()) break;
|
|
9279
9329
|
const neighborPerm = swapNeighbor(currentPerm, rng);
|
|
9280
9330
|
const neighborSchedule = decodePermutation(neighborPerm, problem);
|
|
9281
9331
|
const neighborMakespan = computeMakespan(neighborSchedule);
|
|
@@ -9287,6 +9337,7 @@ function createSASolver(config) {
|
|
|
9287
9337
|
if (currentMakespan < bestMakespan) {
|
|
9288
9338
|
bestSchedule = currentSchedule;
|
|
9289
9339
|
bestMakespan = currentMakespan;
|
|
9340
|
+
pushScheduleTrace(trace, bestSchedule, bestMakespan);
|
|
9290
9341
|
}
|
|
9291
9342
|
}
|
|
9292
9343
|
temperature *= config.coolingRate;
|
|
@@ -9311,7 +9362,8 @@ function createSASolver(config) {
|
|
|
9311
9362
|
makespan: bestMakespan,
|
|
9312
9363
|
schedule: bestSchedule,
|
|
9313
9364
|
elapsedMs: performance.now() - startTime,
|
|
9314
|
-
iterations: config.iterations
|
|
9365
|
+
iterations: config.iterations,
|
|
9366
|
+
trace
|
|
9315
9367
|
});
|
|
9316
9368
|
}
|
|
9317
9369
|
};
|
|
@@ -9326,7 +9378,7 @@ const simulatedAnnealingLargeSolver = createSASolver(SA_CONFIGS[2]);
|
|
|
9326
9378
|
* forbidden for a period. This prevents cycling and forces exploration
|
|
9327
9379
|
* of new regions of the solution space.
|
|
9328
9380
|
*/
|
|
9329
|
-
const ITERATIONS$
|
|
9381
|
+
const ITERATIONS$2 = 1e4;
|
|
9330
9382
|
const TABU_TENURE = 15;
|
|
9331
9383
|
const NEIGHBORHOOD_SIZE = 20;
|
|
9332
9384
|
const tabuSolver = {
|
|
@@ -9335,17 +9387,21 @@ const tabuSolver = {
|
|
|
9335
9387
|
description: "Hill climbing with short-term memory to avoid revisiting recent solutions.",
|
|
9336
9388
|
async solve(problem, options) {
|
|
9337
9389
|
const startTime = performance.now();
|
|
9338
|
-
const
|
|
9390
|
+
const stop = makeScheduleStopper(options, startTime, 15e3);
|
|
9339
9391
|
const rng = createRng$1(42);
|
|
9340
9392
|
let currentPerm = randomPermutation(problem, rng);
|
|
9341
9393
|
let currentSchedule = decodePermutation(currentPerm, problem);
|
|
9342
9394
|
let currentMakespan = computeMakespan(currentSchedule);
|
|
9343
9395
|
let bestSchedule = currentSchedule;
|
|
9344
9396
|
let bestMakespan = currentMakespan;
|
|
9397
|
+
const trace = [{
|
|
9398
|
+
solution: bestSchedule,
|
|
9399
|
+
objective: bestMakespan
|
|
9400
|
+
}];
|
|
9345
9401
|
const tabuList = /* @__PURE__ */ new Map();
|
|
9346
|
-
const progressInterval = Math.max(1, Math.floor(ITERATIONS$
|
|
9347
|
-
for (let iter = 0; iter < ITERATIONS$
|
|
9348
|
-
if (
|
|
9402
|
+
const progressInterval = Math.max(1, Math.floor(ITERATIONS$2 / 100));
|
|
9403
|
+
for (let iter = 0; iter < ITERATIONS$2; iter++) {
|
|
9404
|
+
if (stop()) break;
|
|
9349
9405
|
let bestNeighborPerm = null;
|
|
9350
9406
|
let bestNeighborMakespan = Infinity;
|
|
9351
9407
|
let bestSwapKey = "";
|
|
@@ -9371,6 +9427,7 @@ const tabuSolver = {
|
|
|
9371
9427
|
if (currentMakespan < bestMakespan) {
|
|
9372
9428
|
bestMakespan = currentMakespan;
|
|
9373
9429
|
bestSchedule = currentSchedule;
|
|
9430
|
+
pushScheduleTrace(trace, bestSchedule, bestMakespan);
|
|
9374
9431
|
}
|
|
9375
9432
|
}
|
|
9376
9433
|
if (iter % 100 === 0) {
|
|
@@ -9378,18 +9435,18 @@ const tabuSolver = {
|
|
|
9378
9435
|
}
|
|
9379
9436
|
if (options?.onProgress && iter % progressInterval === 0) options.onProgress({
|
|
9380
9437
|
solverId: "tabu",
|
|
9381
|
-
percentage: Math.round(iter / ITERATIONS$
|
|
9438
|
+
percentage: Math.round(iter / ITERATIONS$2 * 100),
|
|
9382
9439
|
bestObjective: bestMakespan,
|
|
9383
9440
|
currentIteration: iter,
|
|
9384
|
-
totalIterations: ITERATIONS$
|
|
9441
|
+
totalIterations: ITERATIONS$2
|
|
9385
9442
|
});
|
|
9386
9443
|
}
|
|
9387
9444
|
options?.onProgress?.({
|
|
9388
9445
|
solverId: "tabu",
|
|
9389
9446
|
percentage: 100,
|
|
9390
9447
|
bestObjective: bestMakespan,
|
|
9391
|
-
currentIteration: ITERATIONS$
|
|
9392
|
-
totalIterations: ITERATIONS$
|
|
9448
|
+
currentIteration: ITERATIONS$2,
|
|
9449
|
+
totalIterations: ITERATIONS$2
|
|
9393
9450
|
});
|
|
9394
9451
|
return makeSchedulingResult({
|
|
9395
9452
|
solverId: "tabu",
|
|
@@ -9397,7 +9454,8 @@ const tabuSolver = {
|
|
|
9397
9454
|
makespan: bestMakespan,
|
|
9398
9455
|
schedule: bestSchedule,
|
|
9399
9456
|
elapsedMs: performance.now() - startTime,
|
|
9400
|
-
iterations: ITERATIONS$
|
|
9457
|
+
iterations: ITERATIONS$2,
|
|
9458
|
+
trace
|
|
9401
9459
|
});
|
|
9402
9460
|
}
|
|
9403
9461
|
};
|
|
@@ -9417,7 +9475,7 @@ const geneticAlgorithmSolver = {
|
|
|
9417
9475
|
description: "Population-based search with tournament selection, crossover, and mutation.",
|
|
9418
9476
|
async solve(problem, options) {
|
|
9419
9477
|
const startTime = performance.now();
|
|
9420
|
-
const
|
|
9478
|
+
const stop = makeScheduleStopper(options, startTime, 2e4);
|
|
9421
9479
|
const rng = createRng$1(42);
|
|
9422
9480
|
let population = [];
|
|
9423
9481
|
for (let i = 0; i < POPULATION_SIZE; i++) {
|
|
@@ -9429,8 +9487,12 @@ const geneticAlgorithmSolver = {
|
|
|
9429
9487
|
});
|
|
9430
9488
|
}
|
|
9431
9489
|
let bestIndividual = population.reduce((best, ind) => ind.makespan < best.makespan ? ind : best);
|
|
9490
|
+
const trace = [{
|
|
9491
|
+
solution: decodePermutation(bestIndividual.perm, problem),
|
|
9492
|
+
objective: bestIndividual.makespan
|
|
9493
|
+
}];
|
|
9432
9494
|
for (let gen = 0; gen < GENERATIONS; gen++) {
|
|
9433
|
-
if (
|
|
9495
|
+
if (stop()) break;
|
|
9434
9496
|
const newPopulation = [];
|
|
9435
9497
|
newPopulation.push({ ...bestIndividual });
|
|
9436
9498
|
while (newPopulation.length < POPULATION_SIZE) {
|
|
@@ -9446,7 +9508,10 @@ const geneticAlgorithmSolver = {
|
|
|
9446
9508
|
}
|
|
9447
9509
|
population = newPopulation;
|
|
9448
9510
|
const genBest = population.reduce((best, ind) => ind.makespan < best.makespan ? ind : best);
|
|
9449
|
-
if (genBest.makespan < bestIndividual.makespan)
|
|
9511
|
+
if (genBest.makespan < bestIndividual.makespan) {
|
|
9512
|
+
bestIndividual = genBest;
|
|
9513
|
+
pushScheduleTrace(trace, decodePermutation(bestIndividual.perm, problem), bestIndividual.makespan);
|
|
9514
|
+
}
|
|
9450
9515
|
options?.onProgress?.({
|
|
9451
9516
|
solverId: "genetic-algorithm",
|
|
9452
9517
|
percentage: Math.round((gen + 1) / GENERATIONS * 100),
|
|
@@ -9462,7 +9527,8 @@ const geneticAlgorithmSolver = {
|
|
|
9462
9527
|
makespan: bestIndividual.makespan,
|
|
9463
9528
|
schedule: bestSchedule,
|
|
9464
9529
|
elapsedMs: performance.now() - startTime,
|
|
9465
|
-
iterations: GENERATIONS * POPULATION_SIZE
|
|
9530
|
+
iterations: GENERATIONS * POPULATION_SIZE,
|
|
9531
|
+
trace
|
|
9466
9532
|
});
|
|
9467
9533
|
}
|
|
9468
9534
|
};
|
|
@@ -9507,10 +9573,10 @@ function crossover(parent1, parent2, rng) {
|
|
|
9507
9573
|
* assignments) that appear in good solutions and evaporate over time.
|
|
9508
9574
|
*/
|
|
9509
9575
|
const NUM_ANTS = 20;
|
|
9510
|
-
const ITERATIONS = 100;
|
|
9576
|
+
const ITERATIONS$1 = 100;
|
|
9511
9577
|
const ALPHA = 1;
|
|
9512
9578
|
const BETA = 2;
|
|
9513
|
-
const EVAPORATION = .1;
|
|
9579
|
+
const EVAPORATION$1 = .1;
|
|
9514
9580
|
const Q = 100;
|
|
9515
9581
|
const antColonySolver = {
|
|
9516
9582
|
id: "ant-colony",
|
|
@@ -9518,7 +9584,7 @@ const antColonySolver = {
|
|
|
9518
9584
|
description: "Swarm intelligence using pheromone trails to guide solution construction.",
|
|
9519
9585
|
async solve(problem, options) {
|
|
9520
9586
|
const startTime = performance.now();
|
|
9521
|
-
const
|
|
9587
|
+
const stop = makeScheduleStopper(options, startTime, 2e4);
|
|
9522
9588
|
const rng = createRng$1(42);
|
|
9523
9589
|
const allOps = buildOperationList(problem);
|
|
9524
9590
|
const numOps = allOps.length;
|
|
@@ -9526,10 +9592,14 @@ const antColonySolver = {
|
|
|
9526
9592
|
const heuristic = allOps.map((ref) => {
|
|
9527
9593
|
return 1 / problem.jobs.find((j) => j.id === ref.jobId).operations[ref.opIndex].duration;
|
|
9528
9594
|
});
|
|
9529
|
-
let bestMakespan = Infinity;
|
|
9530
9595
|
let bestSchedule = decodePermutation(allOps, problem);
|
|
9531
|
-
|
|
9532
|
-
|
|
9596
|
+
let bestMakespan = computeMakespan(bestSchedule);
|
|
9597
|
+
const trace = [{
|
|
9598
|
+
solution: bestSchedule,
|
|
9599
|
+
objective: bestMakespan
|
|
9600
|
+
}];
|
|
9601
|
+
for (let iter = 0; iter < ITERATIONS$1; iter++) {
|
|
9602
|
+
if (stop()) break;
|
|
9533
9603
|
const antSolutions = [];
|
|
9534
9604
|
for (let ant = 0; ant < NUM_ANTS; ant++) {
|
|
9535
9605
|
const perm = constructSolution(allOps, pheromone, heuristic, rng);
|
|
@@ -9542,9 +9612,10 @@ const antColonySolver = {
|
|
|
9542
9612
|
if (makespan < bestMakespan) {
|
|
9543
9613
|
bestMakespan = makespan;
|
|
9544
9614
|
bestSchedule = schedule;
|
|
9615
|
+
pushScheduleTrace(trace, bestSchedule, bestMakespan);
|
|
9545
9616
|
}
|
|
9546
9617
|
}
|
|
9547
|
-
for (let i = 0; i < numOps; i++) for (let j = 0; j < numOps; j++) pheromone[i][j] *= 1 - EVAPORATION;
|
|
9618
|
+
for (let i = 0; i < numOps; i++) for (let j = 0; j < numOps; j++) pheromone[i][j] *= 1 - EVAPORATION$1;
|
|
9548
9619
|
for (const solution of antSolutions) {
|
|
9549
9620
|
const deposit = Q / solution.makespan;
|
|
9550
9621
|
for (let pos = 0; pos < solution.perm.length; pos++) {
|
|
@@ -9554,10 +9625,10 @@ const antColonySolver = {
|
|
|
9554
9625
|
}
|
|
9555
9626
|
options?.onProgress?.({
|
|
9556
9627
|
solverId: "ant-colony",
|
|
9557
|
-
percentage: Math.round((iter + 1) / ITERATIONS * 100),
|
|
9628
|
+
percentage: Math.round((iter + 1) / ITERATIONS$1 * 100),
|
|
9558
9629
|
bestObjective: bestMakespan,
|
|
9559
9630
|
currentIteration: iter + 1,
|
|
9560
|
-
totalIterations: ITERATIONS
|
|
9631
|
+
totalIterations: ITERATIONS$1
|
|
9561
9632
|
});
|
|
9562
9633
|
}
|
|
9563
9634
|
return makeSchedulingResult({
|
|
@@ -9566,7 +9637,8 @@ const antColonySolver = {
|
|
|
9566
9637
|
makespan: bestMakespan,
|
|
9567
9638
|
schedule: bestSchedule,
|
|
9568
9639
|
elapsedMs: performance.now() - startTime,
|
|
9569
|
-
iterations: ITERATIONS * NUM_ANTS
|
|
9640
|
+
iterations: ITERATIONS$1 * NUM_ANTS,
|
|
9641
|
+
trace
|
|
9570
9642
|
});
|
|
9571
9643
|
}
|
|
9572
9644
|
};
|
|
@@ -9813,23 +9885,18 @@ function validateSchedule(problem, schedule) {
|
|
|
9813
9885
|
errors
|
|
9814
9886
|
};
|
|
9815
9887
|
}
|
|
9816
|
-
|
|
9817
|
-
const MAX_TOTAL_OPS = 80;
|
|
9818
|
-
const MAX_OPS_PER_MACHINE = 8;
|
|
9819
|
-
/**
|
|
9820
|
-
* Load HiGHS - creates FRESH instance each time.
|
|
9821
|
-
*
|
|
9822
|
-
* We intentionally do NOT cache the HiGHS instance.
|
|
9823
|
-
* Caching causes WASM corruption errors.
|
|
9824
|
-
*/
|
|
9888
|
+
/** Load a fresh HiGHS WASM instance (never cache it — see file header). */
|
|
9825
9889
|
async function loadHiGHS() {
|
|
9826
9890
|
const highsLoader = (await import("highs")).default;
|
|
9827
|
-
return
|
|
9891
|
+
return highsLoader({ locateFile: (file) => {
|
|
9828
9892
|
const globalSelf = globalThis;
|
|
9829
9893
|
if (globalSelf.location?.origin) return `${globalSelf.location.origin}/${file}`;
|
|
9830
9894
|
return file;
|
|
9831
9895
|
} });
|
|
9832
9896
|
}
|
|
9897
|
+
const MAX_BINARY_VARS = 150;
|
|
9898
|
+
const MAX_TOTAL_OPS = 80;
|
|
9899
|
+
const MAX_OPS_PER_MACHINE = 8;
|
|
9833
9900
|
function elapsed(startTime) {
|
|
9834
9901
|
return typeof performance !== "undefined" ? performance.now() - startTime : Date.now() - startTime;
|
|
9835
9902
|
}
|
|
@@ -9861,6 +9928,21 @@ const highsSolver = {
|
|
|
9861
9928
|
const lpString = generateLPFormulation(problem);
|
|
9862
9929
|
if (!lpString.includes("Subject To") || !lpString.includes("Bounds")) throw new Error("Invalid LP formulation - missing required sections");
|
|
9863
9930
|
reportProgress(20);
|
|
9931
|
+
if (options?.shouldCancel?.()) {
|
|
9932
|
+
const g = await greedySolver.solve(problem, {});
|
|
9933
|
+
return makeSchedulingResult({
|
|
9934
|
+
solverId: "highs",
|
|
9935
|
+
solverName: "HiGHS (WASM)",
|
|
9936
|
+
makespan: g.objective,
|
|
9937
|
+
schedule: g.solution,
|
|
9938
|
+
elapsedMs: elapsed(startTime),
|
|
9939
|
+
iterations: 0,
|
|
9940
|
+
metadata: {
|
|
9941
|
+
usedFallback: true,
|
|
9942
|
+
reason: "cancelled before HiGHS solve"
|
|
9943
|
+
}
|
|
9944
|
+
});
|
|
9945
|
+
}
|
|
9864
9946
|
let solution;
|
|
9865
9947
|
try {
|
|
9866
9948
|
solution = highs.solve(lpString, {
|
|
@@ -9899,7 +9981,11 @@ const highsSolver = {
|
|
|
9899
9981
|
makespan,
|
|
9900
9982
|
schedule,
|
|
9901
9983
|
elapsedMs: elapsed(startTime),
|
|
9902
|
-
iterations: 1
|
|
9984
|
+
iterations: 1,
|
|
9985
|
+
trace: [{
|
|
9986
|
+
solution: schedule,
|
|
9987
|
+
objective: makespan
|
|
9988
|
+
}]
|
|
9903
9989
|
});
|
|
9904
9990
|
} catch (error) {
|
|
9905
9991
|
reportProgress(0);
|
|
@@ -10544,31 +10630,39 @@ const allSolvers = [
|
|
|
10544
10630
|
solverId: "qaoa-local",
|
|
10545
10631
|
percentage: pct
|
|
10546
10632
|
});
|
|
10633
|
+
const cancelled = () => options.shouldCancel?.() ?? false;
|
|
10547
10634
|
progress(0);
|
|
10548
10635
|
const greedyResult = await greedySolver.solve(problem, {});
|
|
10549
10636
|
progress(10);
|
|
10550
10637
|
const greedyMakespan = greedyResult.objective;
|
|
10551
10638
|
const greedySchedule = greedyResult.solution;
|
|
10639
|
+
const greedyFallback = (reason) => makeSchedulingResult({
|
|
10640
|
+
solverId: "qaoa-local",
|
|
10641
|
+
solverName: "QAOA (Local)",
|
|
10642
|
+
makespan: greedyMakespan,
|
|
10643
|
+
schedule: greedySchedule,
|
|
10644
|
+
elapsedMs: elapsed(),
|
|
10645
|
+
trace: [{
|
|
10646
|
+
solution: greedySchedule,
|
|
10647
|
+
objective: greedyMakespan
|
|
10648
|
+
}],
|
|
10649
|
+
metadata: {
|
|
10650
|
+
layers: LAYERS$1,
|
|
10651
|
+
shots: 0,
|
|
10652
|
+
gamma: 0,
|
|
10653
|
+
beta: 0,
|
|
10654
|
+
rawMakespan: greedyMakespan,
|
|
10655
|
+
usedFallback: true,
|
|
10656
|
+
reason
|
|
10657
|
+
}
|
|
10658
|
+
});
|
|
10552
10659
|
const encoded = encodeSchedulingWithMetadata(problem, greedyMakespan);
|
|
10553
10660
|
const numQubits = encoded.qubo.size;
|
|
10554
10661
|
if (numQubits > MAX_QUBITS || numQubits === 0) {
|
|
10555
10662
|
progress(100);
|
|
10556
|
-
return
|
|
10557
|
-
solverId: "qaoa-local",
|
|
10558
|
-
solverName: "QAOA (Local)",
|
|
10559
|
-
makespan: greedyMakespan,
|
|
10560
|
-
schedule: greedySchedule,
|
|
10561
|
-
elapsedMs: elapsed(),
|
|
10562
|
-
metadata: {
|
|
10563
|
-
layers: LAYERS$1,
|
|
10564
|
-
shots: 0,
|
|
10565
|
-
gamma: 0,
|
|
10566
|
-
beta: 0,
|
|
10567
|
-
rawMakespan: greedyMakespan,
|
|
10568
|
-
usedFallback: true
|
|
10569
|
-
}
|
|
10570
|
-
});
|
|
10663
|
+
return greedyFallback(numQubits === 0 ? "no qubits to encode" : `instance needs ${numQubits} qubits (cap ${MAX_QUBITS})`);
|
|
10571
10664
|
}
|
|
10665
|
+
if (cancelled()) return greedyFallback("cancelled");
|
|
10572
10666
|
const ising = quboToIsing(encoded.qubo);
|
|
10573
10667
|
const backend = new LocalSimBackend();
|
|
10574
10668
|
progress(20);
|
|
@@ -10578,6 +10672,7 @@ const allSolvers = [
|
|
|
10578
10672
|
p: LAYERS$1
|
|
10579
10673
|
});
|
|
10580
10674
|
progress(75);
|
|
10675
|
+
if (cancelled()) return greedyFallback("cancelled");
|
|
10581
10676
|
const gates = buildQAOACircuit(numQubits, ising, [gamma], [beta], LAYERS$1);
|
|
10582
10677
|
const { probabilities } = await backend.run(numQubits, gates);
|
|
10583
10678
|
const samples = sampleFromProbabilities(probabilities, FINAL_SHOTS$1);
|
|
@@ -10594,6 +10689,13 @@ const allSolvers = [
|
|
|
10594
10689
|
makespan: winnerMakespan,
|
|
10595
10690
|
schedule: winnerSchedule,
|
|
10596
10691
|
elapsedMs: elapsed(),
|
|
10692
|
+
trace: [{
|
|
10693
|
+
solution: greedySchedule,
|
|
10694
|
+
objective: greedyMakespan
|
|
10695
|
+
}, {
|
|
10696
|
+
solution: winnerSchedule,
|
|
10697
|
+
objective: winnerMakespan
|
|
10698
|
+
}],
|
|
10597
10699
|
metadata: {
|
|
10598
10700
|
layers: LAYERS$1,
|
|
10599
10701
|
shots: FINAL_SHOTS$1,
|
|
@@ -10901,54 +11003,1966 @@ No markdown, no explanation, no code blocks — just the raw JSON object.`;
|
|
|
10901
11003
|
" \\/ <- fit here",
|
|
10902
11004
|
"Minimize: sum(error^2)"
|
|
10903
11005
|
].join("\n");
|
|
10904
|
-
|
|
10905
|
-
|
|
10906
|
-
|
|
10907
|
-
|
|
10908
|
-
|
|
10909
|
-
|
|
10910
|
-
|
|
10911
|
-
|
|
10912
|
-
|
|
10913
|
-
|
|
10914
|
-
|
|
10915
|
-
|
|
10916
|
-
|
|
10917
|
-
|
|
11006
|
+
const routingSampleProblems = [
|
|
11007
|
+
{
|
|
11008
|
+
family: "routing",
|
|
11009
|
+
name: "Austin Food Truck Circuit",
|
|
11010
|
+
description: "A food truck owner wants the shortest nightly loop hitting ten Austin hotspots, starting and ending at the South Lamar commissary.",
|
|
11011
|
+
nodes: [
|
|
11012
|
+
{
|
|
11013
|
+
id: 0,
|
|
11014
|
+
name: "Commissary (S Lamar)",
|
|
11015
|
+
x: 38,
|
|
11016
|
+
y: 72
|
|
11017
|
+
},
|
|
11018
|
+
{
|
|
11019
|
+
id: 1,
|
|
11020
|
+
name: "Zilker Park",
|
|
11021
|
+
x: 30,
|
|
11022
|
+
y: 58
|
|
11023
|
+
},
|
|
11024
|
+
{
|
|
11025
|
+
id: 2,
|
|
11026
|
+
name: "Rainey St",
|
|
11027
|
+
x: 56,
|
|
11028
|
+
y: 60
|
|
11029
|
+
},
|
|
11030
|
+
{
|
|
11031
|
+
id: 3,
|
|
11032
|
+
name: "6th & Red River",
|
|
11033
|
+
x: 54,
|
|
11034
|
+
y: 48
|
|
11035
|
+
},
|
|
11036
|
+
{
|
|
11037
|
+
id: 4,
|
|
11038
|
+
name: "UT Campus",
|
|
11039
|
+
x: 52,
|
|
11040
|
+
y: 32
|
|
11041
|
+
},
|
|
11042
|
+
{
|
|
11043
|
+
id: 5,
|
|
11044
|
+
name: "Mueller Market",
|
|
11045
|
+
x: 72,
|
|
11046
|
+
y: 30
|
|
11047
|
+
},
|
|
11048
|
+
{
|
|
11049
|
+
id: 6,
|
|
11050
|
+
name: "East Cesar Chavez",
|
|
11051
|
+
x: 70,
|
|
11052
|
+
y: 56
|
|
11053
|
+
},
|
|
11054
|
+
{
|
|
11055
|
+
id: 7,
|
|
11056
|
+
name: "Barton Springs",
|
|
11057
|
+
x: 34,
|
|
11058
|
+
y: 64
|
|
11059
|
+
},
|
|
11060
|
+
{
|
|
11061
|
+
id: 8,
|
|
11062
|
+
name: "The Domain",
|
|
11063
|
+
x: 44,
|
|
11064
|
+
y: 8
|
|
11065
|
+
},
|
|
11066
|
+
{
|
|
11067
|
+
id: 9,
|
|
11068
|
+
name: "Oak Hill",
|
|
11069
|
+
x: 12,
|
|
11070
|
+
y: 86
|
|
11071
|
+
}
|
|
11072
|
+
]
|
|
11073
|
+
},
|
|
11074
|
+
{
|
|
11075
|
+
family: "routing",
|
|
11076
|
+
name: "Kyiv Drone Resupply Run",
|
|
11077
|
+
description: "A logistics drone must visit twelve forward supply caches and return to base on one battery. Every wasted kilometer is flight time the battery does not have.",
|
|
11078
|
+
nodes: [
|
|
11079
|
+
{
|
|
11080
|
+
id: 0,
|
|
11081
|
+
name: "Base",
|
|
11082
|
+
x: 50,
|
|
11083
|
+
y: 92
|
|
11084
|
+
},
|
|
11085
|
+
{
|
|
11086
|
+
id: 1,
|
|
11087
|
+
name: "Cache Alpha",
|
|
11088
|
+
x: 18,
|
|
11089
|
+
y: 74
|
|
11090
|
+
},
|
|
11091
|
+
{
|
|
11092
|
+
id: 2,
|
|
11093
|
+
name: "Cache Bravo",
|
|
11094
|
+
x: 10,
|
|
11095
|
+
y: 48
|
|
11096
|
+
},
|
|
11097
|
+
{
|
|
11098
|
+
id: 3,
|
|
11099
|
+
name: "Cache Charlie",
|
|
11100
|
+
x: 24,
|
|
11101
|
+
y: 22
|
|
11102
|
+
},
|
|
11103
|
+
{
|
|
11104
|
+
id: 4,
|
|
11105
|
+
name: "Cache Delta",
|
|
11106
|
+
x: 44,
|
|
11107
|
+
y: 10
|
|
11108
|
+
},
|
|
11109
|
+
{
|
|
11110
|
+
id: 5,
|
|
11111
|
+
name: "Cache Echo",
|
|
11112
|
+
x: 66,
|
|
11113
|
+
y: 14
|
|
11114
|
+
},
|
|
11115
|
+
{
|
|
11116
|
+
id: 6,
|
|
11117
|
+
name: "Cache Foxtrot",
|
|
11118
|
+
x: 86,
|
|
11119
|
+
y: 26
|
|
11120
|
+
},
|
|
11121
|
+
{
|
|
11122
|
+
id: 7,
|
|
11123
|
+
name: "Cache Golf",
|
|
11124
|
+
x: 92,
|
|
11125
|
+
y: 52
|
|
11126
|
+
},
|
|
11127
|
+
{
|
|
11128
|
+
id: 8,
|
|
11129
|
+
name: "Cache Hotel",
|
|
11130
|
+
x: 80,
|
|
11131
|
+
y: 72
|
|
11132
|
+
},
|
|
11133
|
+
{
|
|
11134
|
+
id: 9,
|
|
11135
|
+
name: "Cache India",
|
|
11136
|
+
x: 62,
|
|
11137
|
+
y: 56
|
|
11138
|
+
},
|
|
11139
|
+
{
|
|
11140
|
+
id: 10,
|
|
11141
|
+
name: "Cache Juliet",
|
|
11142
|
+
x: 38,
|
|
11143
|
+
y: 44
|
|
11144
|
+
},
|
|
11145
|
+
{
|
|
11146
|
+
id: 11,
|
|
11147
|
+
name: "Cache Kilo",
|
|
11148
|
+
x: 30,
|
|
11149
|
+
y: 60
|
|
11150
|
+
}
|
|
11151
|
+
]
|
|
11152
|
+
},
|
|
11153
|
+
{
|
|
11154
|
+
family: "routing",
|
|
11155
|
+
name: "Hill Country Brewery Tour",
|
|
11156
|
+
description: "Eight breweries, one designated-driver van, and a hard rule: end where you started. Minimize the drive so there is more time for the beer.",
|
|
11157
|
+
nodes: [
|
|
11158
|
+
{
|
|
11159
|
+
id: 0,
|
|
11160
|
+
name: "Depot (Dripping Springs)",
|
|
11161
|
+
x: 20,
|
|
11162
|
+
y: 60
|
|
11163
|
+
},
|
|
11164
|
+
{
|
|
11165
|
+
id: 1,
|
|
11166
|
+
name: "Jester King",
|
|
11167
|
+
x: 32,
|
|
11168
|
+
y: 48
|
|
11169
|
+
},
|
|
11170
|
+
{
|
|
11171
|
+
id: 2,
|
|
11172
|
+
name: "Vista Brewing",
|
|
11173
|
+
x: 16,
|
|
11174
|
+
y: 78
|
|
11175
|
+
},
|
|
11176
|
+
{
|
|
11177
|
+
id: 3,
|
|
11178
|
+
name: "Treaty Oak",
|
|
11179
|
+
x: 28,
|
|
11180
|
+
y: 70
|
|
11181
|
+
},
|
|
11182
|
+
{
|
|
11183
|
+
id: 4,
|
|
11184
|
+
name: "Last Stand",
|
|
11185
|
+
x: 46,
|
|
11186
|
+
y: 38
|
|
11187
|
+
},
|
|
11188
|
+
{
|
|
11189
|
+
id: 5,
|
|
11190
|
+
name: "Fitzhugh Brewing",
|
|
11191
|
+
x: 40,
|
|
11192
|
+
y: 56
|
|
11193
|
+
},
|
|
11194
|
+
{
|
|
11195
|
+
id: 6,
|
|
11196
|
+
name: "Family Business",
|
|
11197
|
+
x: 60,
|
|
11198
|
+
y: 30
|
|
11199
|
+
},
|
|
11200
|
+
{
|
|
11201
|
+
id: 7,
|
|
11202
|
+
name: "Suds Monkey",
|
|
11203
|
+
x: 24,
|
|
11204
|
+
y: 52
|
|
11205
|
+
}
|
|
11206
|
+
]
|
|
11207
|
+
}
|
|
11208
|
+
];
|
|
11209
|
+
const packingSampleProblems = [
|
|
11210
|
+
{
|
|
11211
|
+
family: "packing",
|
|
11212
|
+
name: "Mars Cargo Manifest",
|
|
11213
|
+
description: "Fourteen payload modules must ride to orbit in standardized cargo pods. Every pod you do not launch saves nine figures.",
|
|
11214
|
+
binCapacity: 100,
|
|
11215
|
+
binLabel: "pod",
|
|
11216
|
+
items: [
|
|
11217
|
+
{
|
|
11218
|
+
id: 0,
|
|
11219
|
+
name: "Habitat Frame",
|
|
11220
|
+
size: 62
|
|
11221
|
+
},
|
|
11222
|
+
{
|
|
11223
|
+
id: 1,
|
|
11224
|
+
name: "Water Recycler",
|
|
11225
|
+
size: 48
|
|
11226
|
+
},
|
|
11227
|
+
{
|
|
11228
|
+
id: 2,
|
|
11229
|
+
name: "Solar Array A",
|
|
11230
|
+
size: 55
|
|
11231
|
+
},
|
|
11232
|
+
{
|
|
11233
|
+
id: 3,
|
|
11234
|
+
name: "Solar Array B",
|
|
11235
|
+
size: 55
|
|
11236
|
+
},
|
|
11237
|
+
{
|
|
11238
|
+
id: 4,
|
|
11239
|
+
name: "Rover Chassis",
|
|
11240
|
+
size: 70
|
|
11241
|
+
},
|
|
11242
|
+
{
|
|
11243
|
+
id: 5,
|
|
11244
|
+
name: "Lab Module",
|
|
11245
|
+
size: 38
|
|
11246
|
+
},
|
|
11247
|
+
{
|
|
11248
|
+
id: 6,
|
|
11249
|
+
name: "Greenhouse Kit",
|
|
11250
|
+
size: 42
|
|
11251
|
+
},
|
|
11252
|
+
{
|
|
11253
|
+
id: 7,
|
|
11254
|
+
name: "Battery Bank",
|
|
11255
|
+
size: 30
|
|
11256
|
+
},
|
|
11257
|
+
{
|
|
11258
|
+
id: 8,
|
|
11259
|
+
name: "Antenna Mast",
|
|
11260
|
+
size: 22
|
|
11261
|
+
},
|
|
11262
|
+
{
|
|
11263
|
+
id: 9,
|
|
11264
|
+
name: "Med Bay Kit",
|
|
11265
|
+
size: 26
|
|
11266
|
+
},
|
|
11267
|
+
{
|
|
11268
|
+
id: 10,
|
|
11269
|
+
name: "Spare Parts Crate",
|
|
11270
|
+
size: 18
|
|
11271
|
+
},
|
|
11272
|
+
{
|
|
11273
|
+
id: 11,
|
|
11274
|
+
name: "Food Stores",
|
|
11275
|
+
size: 44
|
|
11276
|
+
},
|
|
11277
|
+
{
|
|
11278
|
+
id: 12,
|
|
11279
|
+
name: "Drill Assembly",
|
|
11280
|
+
size: 34
|
|
11281
|
+
},
|
|
11282
|
+
{
|
|
11283
|
+
id: 13,
|
|
11284
|
+
name: "3D Printer",
|
|
11285
|
+
size: 16
|
|
11286
|
+
}
|
|
11287
|
+
]
|
|
11288
|
+
},
|
|
11289
|
+
{
|
|
11290
|
+
family: "packing",
|
|
11291
|
+
name: "Moving Day — Oak Hill",
|
|
11292
|
+
description: "Everything Erik owns has to fit into rented trucks. Each truck costs $180 a day, so the optimizer IS the budget.",
|
|
11293
|
+
binCapacity: 80,
|
|
11294
|
+
binLabel: "truck",
|
|
11295
|
+
items: [
|
|
11296
|
+
{
|
|
11297
|
+
id: 0,
|
|
11298
|
+
name: "Couch",
|
|
11299
|
+
size: 40
|
|
11300
|
+
},
|
|
11301
|
+
{
|
|
11302
|
+
id: 1,
|
|
11303
|
+
name: "Bed Frame",
|
|
11304
|
+
size: 32
|
|
11305
|
+
},
|
|
11306
|
+
{
|
|
11307
|
+
id: 2,
|
|
11308
|
+
name: "Mattress",
|
|
11309
|
+
size: 28
|
|
11310
|
+
},
|
|
11311
|
+
{
|
|
11312
|
+
id: 3,
|
|
11313
|
+
name: "Dining Table",
|
|
11314
|
+
size: 30
|
|
11315
|
+
},
|
|
11316
|
+
{
|
|
11317
|
+
id: 4,
|
|
11318
|
+
name: "Bookshelves",
|
|
11319
|
+
size: 24
|
|
11320
|
+
},
|
|
11321
|
+
{
|
|
11322
|
+
id: 5,
|
|
11323
|
+
name: "Desk Battlestation",
|
|
11324
|
+
size: 36
|
|
11325
|
+
},
|
|
11326
|
+
{
|
|
11327
|
+
id: 6,
|
|
11328
|
+
name: "Arcade Cabinet",
|
|
11329
|
+
size: 44
|
|
11330
|
+
},
|
|
11331
|
+
{
|
|
11332
|
+
id: 7,
|
|
11333
|
+
name: "Kitchen Boxes",
|
|
11334
|
+
size: 20
|
|
11335
|
+
},
|
|
11336
|
+
{
|
|
11337
|
+
id: 8,
|
|
11338
|
+
name: "Book Boxes",
|
|
11339
|
+
size: 26
|
|
11340
|
+
},
|
|
11341
|
+
{
|
|
11342
|
+
id: 9,
|
|
11343
|
+
name: "Garage Tools",
|
|
11344
|
+
size: 18
|
|
11345
|
+
},
|
|
11346
|
+
{
|
|
11347
|
+
id: 10,
|
|
11348
|
+
name: "Bikes",
|
|
11349
|
+
size: 16
|
|
11350
|
+
},
|
|
11351
|
+
{
|
|
11352
|
+
id: 11,
|
|
11353
|
+
name: "Server Rack",
|
|
11354
|
+
size: 22
|
|
11355
|
+
}
|
|
11356
|
+
]
|
|
11357
|
+
},
|
|
11358
|
+
{
|
|
11359
|
+
family: "packing",
|
|
11360
|
+
name: "Server Rack Tetris",
|
|
11361
|
+
description: "Thirteen VM workloads need hosts. Each host burns power whether it is full or idle — consolidate or pay.",
|
|
11362
|
+
binCapacity: 64,
|
|
11363
|
+
binLabel: "host",
|
|
11364
|
+
items: [
|
|
11365
|
+
{
|
|
11366
|
+
id: 0,
|
|
11367
|
+
name: "Postgres Primary",
|
|
11368
|
+
size: 32
|
|
11369
|
+
},
|
|
11370
|
+
{
|
|
11371
|
+
id: 1,
|
|
11372
|
+
name: "Postgres Replica",
|
|
11373
|
+
size: 24
|
|
11374
|
+
},
|
|
11375
|
+
{
|
|
11376
|
+
id: 2,
|
|
11377
|
+
name: "Web Frontend x4",
|
|
11378
|
+
size: 16
|
|
11379
|
+
},
|
|
11380
|
+
{
|
|
11381
|
+
id: 3,
|
|
11382
|
+
name: "API Cluster",
|
|
11383
|
+
size: 28
|
|
11384
|
+
},
|
|
11385
|
+
{
|
|
11386
|
+
id: 4,
|
|
11387
|
+
name: "Redis Cache",
|
|
11388
|
+
size: 12
|
|
11389
|
+
},
|
|
11390
|
+
{
|
|
11391
|
+
id: 5,
|
|
11392
|
+
name: "ML Inference",
|
|
11393
|
+
size: 48
|
|
11394
|
+
},
|
|
11395
|
+
{
|
|
11396
|
+
id: 6,
|
|
11397
|
+
name: "CI Runners",
|
|
11398
|
+
size: 20
|
|
11399
|
+
},
|
|
11400
|
+
{
|
|
11401
|
+
id: 7,
|
|
11402
|
+
name: "Log Pipeline",
|
|
11403
|
+
size: 14
|
|
11404
|
+
},
|
|
11405
|
+
{
|
|
11406
|
+
id: 8,
|
|
11407
|
+
name: "Metrics Stack",
|
|
11408
|
+
size: 18
|
|
11409
|
+
},
|
|
11410
|
+
{
|
|
11411
|
+
id: 9,
|
|
11412
|
+
name: "Batch ETL",
|
|
11413
|
+
size: 26
|
|
11414
|
+
},
|
|
11415
|
+
{
|
|
11416
|
+
id: 10,
|
|
11417
|
+
name: "Search Index",
|
|
11418
|
+
size: 22
|
|
11419
|
+
},
|
|
11420
|
+
{
|
|
11421
|
+
id: 11,
|
|
11422
|
+
name: "Mail Service",
|
|
11423
|
+
size: 8
|
|
11424
|
+
},
|
|
11425
|
+
{
|
|
11426
|
+
id: 12,
|
|
11427
|
+
name: "Backup Agent",
|
|
11428
|
+
size: 10
|
|
11429
|
+
}
|
|
11430
|
+
]
|
|
11431
|
+
}
|
|
11432
|
+
];
|
|
11433
|
+
const assignmentSampleProblems = [
|
|
11434
|
+
{
|
|
11435
|
+
family: "assignment",
|
|
11436
|
+
name: "Raid Roster",
|
|
11437
|
+
description: "Eight raiders, eight roles, one progression night. The cost matrix is each player's discomfort in each role — minimize total grumbling.",
|
|
11438
|
+
agents: [
|
|
11439
|
+
{
|
|
11440
|
+
id: 0,
|
|
11441
|
+
name: "Thorgrim"
|
|
11442
|
+
},
|
|
11443
|
+
{
|
|
11444
|
+
id: 1,
|
|
11445
|
+
name: "Lyralei"
|
|
11446
|
+
},
|
|
11447
|
+
{
|
|
11448
|
+
id: 2,
|
|
11449
|
+
name: "Mogrash"
|
|
11450
|
+
},
|
|
11451
|
+
{
|
|
11452
|
+
id: 3,
|
|
11453
|
+
name: "Seraphine"
|
|
11454
|
+
},
|
|
11455
|
+
{
|
|
11456
|
+
id: 4,
|
|
11457
|
+
name: "Kettle"
|
|
11458
|
+
},
|
|
11459
|
+
{
|
|
11460
|
+
id: 5,
|
|
11461
|
+
name: "Vexx"
|
|
11462
|
+
},
|
|
11463
|
+
{
|
|
11464
|
+
id: 6,
|
|
11465
|
+
name: "Oakenheart"
|
|
11466
|
+
},
|
|
11467
|
+
{
|
|
11468
|
+
id: 7,
|
|
11469
|
+
name: "Zinnia"
|
|
11470
|
+
}
|
|
11471
|
+
],
|
|
11472
|
+
tasks: [
|
|
11473
|
+
{
|
|
11474
|
+
id: 0,
|
|
11475
|
+
name: "Main Tank"
|
|
11476
|
+
},
|
|
11477
|
+
{
|
|
11478
|
+
id: 1,
|
|
11479
|
+
name: "Off Tank"
|
|
11480
|
+
},
|
|
11481
|
+
{
|
|
11482
|
+
id: 2,
|
|
11483
|
+
name: "Healer 1"
|
|
11484
|
+
},
|
|
11485
|
+
{
|
|
11486
|
+
id: 3,
|
|
11487
|
+
name: "Healer 2"
|
|
11488
|
+
},
|
|
11489
|
+
{
|
|
11490
|
+
id: 4,
|
|
11491
|
+
name: "Melee DPS"
|
|
11492
|
+
},
|
|
11493
|
+
{
|
|
11494
|
+
id: 5,
|
|
11495
|
+
name: "Ranged DPS"
|
|
11496
|
+
},
|
|
11497
|
+
{
|
|
11498
|
+
id: 6,
|
|
11499
|
+
name: "Raid Lead"
|
|
11500
|
+
},
|
|
11501
|
+
{
|
|
11502
|
+
id: 7,
|
|
11503
|
+
name: "Loot Council"
|
|
11504
|
+
}
|
|
11505
|
+
],
|
|
11506
|
+
cost: [
|
|
11507
|
+
[
|
|
11508
|
+
2,
|
|
11509
|
+
4,
|
|
11510
|
+
9,
|
|
11511
|
+
9,
|
|
11512
|
+
5,
|
|
11513
|
+
7,
|
|
11514
|
+
6,
|
|
11515
|
+
8
|
|
11516
|
+
],
|
|
11517
|
+
[
|
|
11518
|
+
9,
|
|
11519
|
+
8,
|
|
11520
|
+
2,
|
|
11521
|
+
3,
|
|
11522
|
+
7,
|
|
11523
|
+
5,
|
|
11524
|
+
6,
|
|
11525
|
+
4
|
|
11526
|
+
],
|
|
11527
|
+
[
|
|
11528
|
+
3,
|
|
11529
|
+
2,
|
|
11530
|
+
9,
|
|
11531
|
+
8,
|
|
11532
|
+
4,
|
|
11533
|
+
6,
|
|
11534
|
+
7,
|
|
11535
|
+
9
|
|
11536
|
+
],
|
|
11537
|
+
[
|
|
11538
|
+
8,
|
|
11539
|
+
9,
|
|
11540
|
+
3,
|
|
11541
|
+
2,
|
|
11542
|
+
6,
|
|
11543
|
+
4,
|
|
11544
|
+
5,
|
|
11545
|
+
6
|
|
11546
|
+
],
|
|
11547
|
+
[
|
|
11548
|
+
7,
|
|
11549
|
+
6,
|
|
11550
|
+
5,
|
|
11551
|
+
5,
|
|
11552
|
+
2,
|
|
11553
|
+
3,
|
|
11554
|
+
8,
|
|
11555
|
+
7
|
|
11556
|
+
],
|
|
11557
|
+
[
|
|
11558
|
+
6,
|
|
11559
|
+
7,
|
|
11560
|
+
6,
|
|
11561
|
+
6,
|
|
11562
|
+
3,
|
|
11563
|
+
2,
|
|
11564
|
+
4,
|
|
11565
|
+
5
|
|
11566
|
+
],
|
|
11567
|
+
[
|
|
11568
|
+
4,
|
|
11569
|
+
3,
|
|
11570
|
+
7,
|
|
11571
|
+
7,
|
|
11572
|
+
5,
|
|
11573
|
+
6,
|
|
11574
|
+
2,
|
|
11575
|
+
3
|
|
11576
|
+
],
|
|
11577
|
+
[
|
|
11578
|
+
9,
|
|
11579
|
+
8,
|
|
11580
|
+
4,
|
|
11581
|
+
4,
|
|
11582
|
+
6,
|
|
11583
|
+
5,
|
|
11584
|
+
3,
|
|
11585
|
+
2
|
|
11586
|
+
]
|
|
11587
|
+
]
|
|
11588
|
+
},
|
|
11589
|
+
{
|
|
11590
|
+
family: "assignment",
|
|
11591
|
+
name: "Surgery Suite Staffing",
|
|
11592
|
+
description: "Six surgeons, six operating rooms with different specialties on the board today. Cost = mismatch between surgeon expertise and case type.",
|
|
11593
|
+
agents: [
|
|
11594
|
+
{
|
|
11595
|
+
id: 0,
|
|
11596
|
+
name: "Dr. Asante"
|
|
11597
|
+
},
|
|
11598
|
+
{
|
|
11599
|
+
id: 1,
|
|
11600
|
+
name: "Dr. Brook"
|
|
11601
|
+
},
|
|
11602
|
+
{
|
|
11603
|
+
id: 2,
|
|
11604
|
+
name: "Dr. Chen"
|
|
11605
|
+
},
|
|
11606
|
+
{
|
|
11607
|
+
id: 3,
|
|
11608
|
+
name: "Dr. Duarte"
|
|
11609
|
+
},
|
|
11610
|
+
{
|
|
11611
|
+
id: 4,
|
|
11612
|
+
name: "Dr. Eze"
|
|
11613
|
+
},
|
|
11614
|
+
{
|
|
11615
|
+
id: 5,
|
|
11616
|
+
name: "Dr. Farrow"
|
|
11617
|
+
}
|
|
11618
|
+
],
|
|
11619
|
+
tasks: [
|
|
11620
|
+
{
|
|
11621
|
+
id: 0,
|
|
11622
|
+
name: "OR-1 Cardiac"
|
|
11623
|
+
},
|
|
11624
|
+
{
|
|
11625
|
+
id: 1,
|
|
11626
|
+
name: "OR-2 Ortho"
|
|
11627
|
+
},
|
|
11628
|
+
{
|
|
11629
|
+
id: 2,
|
|
11630
|
+
name: "OR-3 Neuro"
|
|
11631
|
+
},
|
|
11632
|
+
{
|
|
11633
|
+
id: 3,
|
|
11634
|
+
name: "OR-4 General"
|
|
11635
|
+
},
|
|
11636
|
+
{
|
|
11637
|
+
id: 4,
|
|
11638
|
+
name: "OR-5 Pediatric"
|
|
11639
|
+
},
|
|
11640
|
+
{
|
|
11641
|
+
id: 5,
|
|
11642
|
+
name: "OR-6 Trauma"
|
|
11643
|
+
}
|
|
11644
|
+
],
|
|
11645
|
+
cost: [
|
|
11646
|
+
[
|
|
11647
|
+
1,
|
|
11648
|
+
8,
|
|
11649
|
+
9,
|
|
11650
|
+
4,
|
|
11651
|
+
7,
|
|
11652
|
+
5
|
|
11653
|
+
],
|
|
11654
|
+
[
|
|
11655
|
+
9,
|
|
11656
|
+
1,
|
|
11657
|
+
8,
|
|
11658
|
+
5,
|
|
11659
|
+
6,
|
|
11660
|
+
3
|
|
11661
|
+
],
|
|
11662
|
+
[
|
|
11663
|
+
8,
|
|
11664
|
+
9,
|
|
11665
|
+
1,
|
|
11666
|
+
6,
|
|
11667
|
+
5,
|
|
11668
|
+
7
|
|
11669
|
+
],
|
|
11670
|
+
[
|
|
11671
|
+
5,
|
|
11672
|
+
4,
|
|
11673
|
+
7,
|
|
11674
|
+
1,
|
|
11675
|
+
3,
|
|
11676
|
+
2
|
|
11677
|
+
],
|
|
11678
|
+
[
|
|
11679
|
+
7,
|
|
11680
|
+
6,
|
|
11681
|
+
5,
|
|
11682
|
+
3,
|
|
11683
|
+
1,
|
|
11684
|
+
4
|
|
11685
|
+
],
|
|
11686
|
+
[
|
|
11687
|
+
4,
|
|
11688
|
+
3,
|
|
11689
|
+
6,
|
|
11690
|
+
2,
|
|
11691
|
+
4,
|
|
11692
|
+
1
|
|
11693
|
+
]
|
|
11694
|
+
]
|
|
11695
|
+
},
|
|
11696
|
+
{
|
|
11697
|
+
family: "assignment",
|
|
11698
|
+
name: "Support Ticket Triage",
|
|
11699
|
+
description: "Seven engineers, nine open escalations — two will wait. Cost = estimated hours for each engineer on each ticket given their domain depth.",
|
|
11700
|
+
agents: [
|
|
11701
|
+
{
|
|
11702
|
+
id: 0,
|
|
11703
|
+
name: "Imani"
|
|
11704
|
+
},
|
|
11705
|
+
{
|
|
11706
|
+
id: 1,
|
|
11707
|
+
name: "Jonas"
|
|
11708
|
+
},
|
|
11709
|
+
{
|
|
11710
|
+
id: 2,
|
|
11711
|
+
name: "Kai"
|
|
11712
|
+
},
|
|
11713
|
+
{
|
|
11714
|
+
id: 3,
|
|
11715
|
+
name: "Lena"
|
|
11716
|
+
},
|
|
11717
|
+
{
|
|
11718
|
+
id: 4,
|
|
11719
|
+
name: "Marcus"
|
|
11720
|
+
},
|
|
11721
|
+
{
|
|
11722
|
+
id: 5,
|
|
11723
|
+
name: "Noor"
|
|
11724
|
+
},
|
|
11725
|
+
{
|
|
11726
|
+
id: 6,
|
|
11727
|
+
name: "Owen"
|
|
11728
|
+
}
|
|
11729
|
+
],
|
|
11730
|
+
tasks: [
|
|
11731
|
+
{
|
|
11732
|
+
id: 0,
|
|
11733
|
+
name: "Auth outage"
|
|
11734
|
+
},
|
|
11735
|
+
{
|
|
11736
|
+
id: 1,
|
|
11737
|
+
name: "Billing drift"
|
|
11738
|
+
},
|
|
11739
|
+
{
|
|
11740
|
+
id: 2,
|
|
11741
|
+
name: "Mobile crash"
|
|
11742
|
+
},
|
|
11743
|
+
{
|
|
11744
|
+
id: 3,
|
|
11745
|
+
name: "Search latency"
|
|
11746
|
+
},
|
|
11747
|
+
{
|
|
11748
|
+
id: 4,
|
|
11749
|
+
name: "Data export"
|
|
11750
|
+
},
|
|
11751
|
+
{
|
|
11752
|
+
id: 5,
|
|
11753
|
+
name: "Webhook storm"
|
|
11754
|
+
},
|
|
11755
|
+
{
|
|
11756
|
+
id: 6,
|
|
11757
|
+
name: "SSO config"
|
|
11758
|
+
},
|
|
11759
|
+
{
|
|
11760
|
+
id: 7,
|
|
11761
|
+
name: "Rate limiter"
|
|
11762
|
+
},
|
|
11763
|
+
{
|
|
11764
|
+
id: 8,
|
|
11765
|
+
name: "PDF renderer"
|
|
11766
|
+
}
|
|
11767
|
+
],
|
|
11768
|
+
cost: [
|
|
11769
|
+
[
|
|
11770
|
+
2,
|
|
11771
|
+
7,
|
|
11772
|
+
9,
|
|
11773
|
+
6,
|
|
11774
|
+
5,
|
|
11775
|
+
4,
|
|
11776
|
+
3,
|
|
11777
|
+
5,
|
|
11778
|
+
8
|
|
11779
|
+
],
|
|
11780
|
+
[
|
|
11781
|
+
8,
|
|
11782
|
+
2,
|
|
11783
|
+
7,
|
|
11784
|
+
5,
|
|
11785
|
+
3,
|
|
11786
|
+
6,
|
|
11787
|
+
7,
|
|
11788
|
+
6,
|
|
11789
|
+
4
|
|
11790
|
+
],
|
|
11791
|
+
[
|
|
11792
|
+
9,
|
|
11793
|
+
6,
|
|
11794
|
+
2,
|
|
11795
|
+
7,
|
|
11796
|
+
6,
|
|
11797
|
+
5,
|
|
11798
|
+
8,
|
|
11799
|
+
7,
|
|
11800
|
+
3
|
|
11801
|
+
],
|
|
11802
|
+
[
|
|
11803
|
+
4,
|
|
11804
|
+
5,
|
|
11805
|
+
6,
|
|
11806
|
+
2,
|
|
11807
|
+
4,
|
|
11808
|
+
3,
|
|
11809
|
+
5,
|
|
11810
|
+
2,
|
|
11811
|
+
7
|
|
11812
|
+
],
|
|
11813
|
+
[
|
|
11814
|
+
6,
|
|
11815
|
+
3,
|
|
11816
|
+
8,
|
|
11817
|
+
4,
|
|
11818
|
+
2,
|
|
11819
|
+
7,
|
|
11820
|
+
6,
|
|
11821
|
+
5,
|
|
11822
|
+
5
|
|
11823
|
+
],
|
|
11824
|
+
[
|
|
11825
|
+
3,
|
|
11826
|
+
6,
|
|
11827
|
+
5,
|
|
11828
|
+
3,
|
|
11829
|
+
7,
|
|
11830
|
+
2,
|
|
11831
|
+
2,
|
|
11832
|
+
4,
|
|
11833
|
+
6
|
|
11834
|
+
],
|
|
11835
|
+
[
|
|
11836
|
+
7,
|
|
11837
|
+
4,
|
|
11838
|
+
4,
|
|
11839
|
+
8,
|
|
11840
|
+
5,
|
|
11841
|
+
6,
|
|
11842
|
+
4,
|
|
11843
|
+
3,
|
|
11844
|
+
2
|
|
11845
|
+
]
|
|
11846
|
+
]
|
|
11847
|
+
}
|
|
11848
|
+
];
|
|
11849
|
+
const networkSampleProblems = [
|
|
11850
|
+
{
|
|
11851
|
+
family: "network",
|
|
11852
|
+
name: "Office Seating Feud",
|
|
11853
|
+
description: "Ten coworkers, weighted rivalry edges (1 = mild eye-rolls, 5 = open warfare). Split them across two floors so the maximum total rivalry crosses the staircase.",
|
|
11854
|
+
nodes: [
|
|
11855
|
+
{
|
|
11856
|
+
id: 0,
|
|
11857
|
+
name: "Ava",
|
|
11858
|
+
x: 20,
|
|
11859
|
+
y: 20
|
|
11860
|
+
},
|
|
11861
|
+
{
|
|
11862
|
+
id: 1,
|
|
11863
|
+
name: "Ben",
|
|
11864
|
+
x: 50,
|
|
11865
|
+
y: 12
|
|
11866
|
+
},
|
|
11867
|
+
{
|
|
11868
|
+
id: 2,
|
|
11869
|
+
name: "Cleo",
|
|
11870
|
+
x: 80,
|
|
11871
|
+
y: 22
|
|
11872
|
+
},
|
|
11873
|
+
{
|
|
11874
|
+
id: 3,
|
|
11875
|
+
name: "Dex",
|
|
11876
|
+
x: 12,
|
|
11877
|
+
y: 50
|
|
11878
|
+
},
|
|
11879
|
+
{
|
|
11880
|
+
id: 4,
|
|
11881
|
+
name: "Elle",
|
|
11882
|
+
x: 42,
|
|
11883
|
+
y: 42
|
|
11884
|
+
},
|
|
11885
|
+
{
|
|
11886
|
+
id: 5,
|
|
11887
|
+
name: "Finn",
|
|
11888
|
+
x: 70,
|
|
11889
|
+
y: 48
|
|
11890
|
+
},
|
|
11891
|
+
{
|
|
11892
|
+
id: 6,
|
|
11893
|
+
name: "Gus",
|
|
11894
|
+
x: 92,
|
|
11895
|
+
y: 55
|
|
11896
|
+
},
|
|
11897
|
+
{
|
|
11898
|
+
id: 7,
|
|
11899
|
+
name: "Hana",
|
|
11900
|
+
x: 25,
|
|
11901
|
+
y: 80
|
|
11902
|
+
},
|
|
11903
|
+
{
|
|
11904
|
+
id: 8,
|
|
11905
|
+
name: "Iggy",
|
|
11906
|
+
x: 55,
|
|
11907
|
+
y: 84
|
|
11908
|
+
},
|
|
11909
|
+
{
|
|
11910
|
+
id: 9,
|
|
11911
|
+
name: "June",
|
|
11912
|
+
x: 82,
|
|
11913
|
+
y: 80
|
|
11914
|
+
}
|
|
11915
|
+
],
|
|
11916
|
+
edges: [
|
|
11917
|
+
{
|
|
11918
|
+
a: 0,
|
|
11919
|
+
b: 1,
|
|
11920
|
+
w: 3
|
|
11921
|
+
},
|
|
11922
|
+
{
|
|
11923
|
+
a: 0,
|
|
11924
|
+
b: 3,
|
|
11925
|
+
w: 1
|
|
11926
|
+
},
|
|
11927
|
+
{
|
|
11928
|
+
a: 0,
|
|
11929
|
+
b: 4,
|
|
11930
|
+
w: 4
|
|
11931
|
+
},
|
|
11932
|
+
{
|
|
11933
|
+
a: 1,
|
|
11934
|
+
b: 2,
|
|
11935
|
+
w: 2
|
|
11936
|
+
},
|
|
11937
|
+
{
|
|
11938
|
+
a: 1,
|
|
11939
|
+
b: 4,
|
|
11940
|
+
w: 5
|
|
11941
|
+
},
|
|
11942
|
+
{
|
|
11943
|
+
a: 2,
|
|
11944
|
+
b: 5,
|
|
11945
|
+
w: 3
|
|
11946
|
+
},
|
|
11947
|
+
{
|
|
11948
|
+
a: 2,
|
|
11949
|
+
b: 6,
|
|
11950
|
+
w: 1
|
|
11951
|
+
},
|
|
11952
|
+
{
|
|
11953
|
+
a: 3,
|
|
11954
|
+
b: 4,
|
|
11955
|
+
w: 2
|
|
11956
|
+
},
|
|
11957
|
+
{
|
|
11958
|
+
a: 3,
|
|
11959
|
+
b: 7,
|
|
11960
|
+
w: 4
|
|
11961
|
+
},
|
|
11962
|
+
{
|
|
11963
|
+
a: 4,
|
|
11964
|
+
b: 5,
|
|
11965
|
+
w: 1
|
|
11966
|
+
},
|
|
11967
|
+
{
|
|
11968
|
+
a: 4,
|
|
11969
|
+
b: 8,
|
|
11970
|
+
w: 3
|
|
11971
|
+
},
|
|
11972
|
+
{
|
|
11973
|
+
a: 5,
|
|
11974
|
+
b: 6,
|
|
11975
|
+
w: 4
|
|
11976
|
+
},
|
|
11977
|
+
{
|
|
11978
|
+
a: 5,
|
|
11979
|
+
b: 9,
|
|
11980
|
+
w: 2
|
|
11981
|
+
},
|
|
11982
|
+
{
|
|
11983
|
+
a: 6,
|
|
11984
|
+
b: 9,
|
|
11985
|
+
w: 5
|
|
11986
|
+
},
|
|
11987
|
+
{
|
|
11988
|
+
a: 7,
|
|
11989
|
+
b: 8,
|
|
11990
|
+
w: 2
|
|
11991
|
+
},
|
|
11992
|
+
{
|
|
11993
|
+
a: 8,
|
|
11994
|
+
b: 9,
|
|
11995
|
+
w: 1
|
|
11996
|
+
}
|
|
11997
|
+
]
|
|
11998
|
+
},
|
|
11999
|
+
{
|
|
12000
|
+
family: "network",
|
|
12001
|
+
name: "Microservice Fault Domains",
|
|
12002
|
+
description: "Twelve services, edges weighted by cross-talk volume. Split across two availability zones so the heaviest traffic crosses zones — forcing the chattiest pairs to prove they tolerate partition.",
|
|
12003
|
+
nodes: [
|
|
12004
|
+
{
|
|
12005
|
+
id: 0,
|
|
12006
|
+
name: "gateway",
|
|
12007
|
+
x: 50,
|
|
12008
|
+
y: 8
|
|
12009
|
+
},
|
|
12010
|
+
{
|
|
12011
|
+
id: 1,
|
|
12012
|
+
name: "auth",
|
|
12013
|
+
x: 25,
|
|
12014
|
+
y: 22
|
|
12015
|
+
},
|
|
12016
|
+
{
|
|
12017
|
+
id: 2,
|
|
12018
|
+
name: "users",
|
|
12019
|
+
x: 75,
|
|
12020
|
+
y: 22
|
|
12021
|
+
},
|
|
12022
|
+
{
|
|
12023
|
+
id: 3,
|
|
12024
|
+
name: "billing",
|
|
12025
|
+
x: 12,
|
|
12026
|
+
y: 46
|
|
12027
|
+
},
|
|
12028
|
+
{
|
|
12029
|
+
id: 4,
|
|
12030
|
+
name: "catalog",
|
|
12031
|
+
x: 40,
|
|
12032
|
+
y: 40
|
|
12033
|
+
},
|
|
12034
|
+
{
|
|
12035
|
+
id: 5,
|
|
12036
|
+
name: "orders",
|
|
12037
|
+
x: 64,
|
|
12038
|
+
y: 42
|
|
12039
|
+
},
|
|
12040
|
+
{
|
|
12041
|
+
id: 6,
|
|
12042
|
+
name: "search",
|
|
12043
|
+
x: 90,
|
|
12044
|
+
y: 44
|
|
12045
|
+
},
|
|
12046
|
+
{
|
|
12047
|
+
id: 7,
|
|
12048
|
+
name: "ledger",
|
|
12049
|
+
x: 20,
|
|
12050
|
+
y: 70
|
|
12051
|
+
},
|
|
12052
|
+
{
|
|
12053
|
+
id: 8,
|
|
12054
|
+
name: "shipping",
|
|
12055
|
+
x: 48,
|
|
12056
|
+
y: 68
|
|
12057
|
+
},
|
|
12058
|
+
{
|
|
12059
|
+
id: 9,
|
|
12060
|
+
name: "notify",
|
|
12061
|
+
x: 74,
|
|
12062
|
+
y: 70
|
|
12063
|
+
},
|
|
12064
|
+
{
|
|
12065
|
+
id: 10,
|
|
12066
|
+
name: "analytics",
|
|
12067
|
+
x: 34,
|
|
12068
|
+
y: 90
|
|
12069
|
+
},
|
|
12070
|
+
{
|
|
12071
|
+
id: 11,
|
|
12072
|
+
name: "ml-recs",
|
|
12073
|
+
x: 66,
|
|
12074
|
+
y: 90
|
|
12075
|
+
}
|
|
12076
|
+
],
|
|
12077
|
+
edges: [
|
|
12078
|
+
{
|
|
12079
|
+
a: 0,
|
|
12080
|
+
b: 1,
|
|
12081
|
+
w: 5
|
|
12082
|
+
},
|
|
12083
|
+
{
|
|
12084
|
+
a: 0,
|
|
12085
|
+
b: 2,
|
|
12086
|
+
w: 4
|
|
12087
|
+
},
|
|
12088
|
+
{
|
|
12089
|
+
a: 0,
|
|
12090
|
+
b: 4,
|
|
12091
|
+
w: 3
|
|
12092
|
+
},
|
|
12093
|
+
{
|
|
12094
|
+
a: 1,
|
|
12095
|
+
b: 2,
|
|
12096
|
+
w: 2
|
|
12097
|
+
},
|
|
12098
|
+
{
|
|
12099
|
+
a: 1,
|
|
12100
|
+
b: 3,
|
|
12101
|
+
w: 3
|
|
12102
|
+
},
|
|
12103
|
+
{
|
|
12104
|
+
a: 2,
|
|
12105
|
+
b: 5,
|
|
12106
|
+
w: 4
|
|
12107
|
+
},
|
|
12108
|
+
{
|
|
12109
|
+
a: 2,
|
|
12110
|
+
b: 6,
|
|
12111
|
+
w: 2
|
|
12112
|
+
},
|
|
12113
|
+
{
|
|
12114
|
+
a: 3,
|
|
12115
|
+
b: 7,
|
|
12116
|
+
w: 5
|
|
12117
|
+
},
|
|
12118
|
+
{
|
|
12119
|
+
a: 4,
|
|
12120
|
+
b: 5,
|
|
12121
|
+
w: 3
|
|
12122
|
+
},
|
|
12123
|
+
{
|
|
12124
|
+
a: 4,
|
|
12125
|
+
b: 6,
|
|
12126
|
+
w: 2
|
|
12127
|
+
},
|
|
12128
|
+
{
|
|
12129
|
+
a: 4,
|
|
12130
|
+
b: 11,
|
|
12131
|
+
w: 2
|
|
12132
|
+
},
|
|
12133
|
+
{
|
|
12134
|
+
a: 5,
|
|
12135
|
+
b: 8,
|
|
12136
|
+
w: 4
|
|
12137
|
+
},
|
|
12138
|
+
{
|
|
12139
|
+
a: 5,
|
|
12140
|
+
b: 9,
|
|
12141
|
+
w: 2
|
|
12142
|
+
},
|
|
12143
|
+
{
|
|
12144
|
+
a: 7,
|
|
12145
|
+
b: 10,
|
|
12146
|
+
w: 2
|
|
12147
|
+
},
|
|
12148
|
+
{
|
|
12149
|
+
a: 8,
|
|
12150
|
+
b: 9,
|
|
12151
|
+
w: 3
|
|
12152
|
+
},
|
|
12153
|
+
{
|
|
12154
|
+
a: 8,
|
|
12155
|
+
b: 10,
|
|
12156
|
+
w: 1
|
|
12157
|
+
},
|
|
12158
|
+
{
|
|
12159
|
+
a: 9,
|
|
12160
|
+
b: 11,
|
|
12161
|
+
w: 2
|
|
12162
|
+
},
|
|
12163
|
+
{
|
|
12164
|
+
a: 10,
|
|
12165
|
+
b: 11,
|
|
12166
|
+
w: 3
|
|
12167
|
+
}
|
|
12168
|
+
]
|
|
12169
|
+
},
|
|
12170
|
+
{
|
|
12171
|
+
family: "network",
|
|
12172
|
+
name: "Power Grid Islanding",
|
|
12173
|
+
description: "During a storm event, the grid must split into two self-sufficient islands. Maximize the inter-island line capacity you can afford to sever cleanly.",
|
|
12174
|
+
nodes: [
|
|
12175
|
+
{
|
|
12176
|
+
id: 0,
|
|
12177
|
+
name: "Plant North",
|
|
12178
|
+
x: 30,
|
|
12179
|
+
y: 10
|
|
12180
|
+
},
|
|
12181
|
+
{
|
|
12182
|
+
id: 1,
|
|
12183
|
+
name: "Plant South",
|
|
12184
|
+
x: 65,
|
|
12185
|
+
y: 90
|
|
12186
|
+
},
|
|
12187
|
+
{
|
|
12188
|
+
id: 2,
|
|
12189
|
+
name: "Sub Alpha",
|
|
12190
|
+
x: 15,
|
|
12191
|
+
y: 35
|
|
12192
|
+
},
|
|
12193
|
+
{
|
|
12194
|
+
id: 3,
|
|
12195
|
+
name: "Sub Bravo",
|
|
12196
|
+
x: 50,
|
|
12197
|
+
y: 28
|
|
12198
|
+
},
|
|
12199
|
+
{
|
|
12200
|
+
id: 4,
|
|
12201
|
+
name: "Sub Charlie",
|
|
12202
|
+
x: 85,
|
|
12203
|
+
y: 32
|
|
12204
|
+
},
|
|
12205
|
+
{
|
|
12206
|
+
id: 5,
|
|
12207
|
+
name: "Sub Delta",
|
|
12208
|
+
x: 25,
|
|
12209
|
+
y: 62
|
|
12210
|
+
},
|
|
12211
|
+
{
|
|
12212
|
+
id: 6,
|
|
12213
|
+
name: "Sub Echo",
|
|
12214
|
+
x: 58,
|
|
12215
|
+
y: 58
|
|
12216
|
+
},
|
|
12217
|
+
{
|
|
12218
|
+
id: 7,
|
|
12219
|
+
name: "Sub Foxtrot",
|
|
12220
|
+
x: 88,
|
|
12221
|
+
y: 66
|
|
12222
|
+
},
|
|
12223
|
+
{
|
|
12224
|
+
id: 8,
|
|
12225
|
+
name: "City West",
|
|
12226
|
+
x: 12,
|
|
12227
|
+
y: 88
|
|
12228
|
+
}
|
|
12229
|
+
],
|
|
12230
|
+
edges: [
|
|
12231
|
+
{
|
|
12232
|
+
a: 0,
|
|
12233
|
+
b: 2,
|
|
12234
|
+
w: 4
|
|
12235
|
+
},
|
|
12236
|
+
{
|
|
12237
|
+
a: 0,
|
|
12238
|
+
b: 3,
|
|
12239
|
+
w: 5
|
|
12240
|
+
},
|
|
12241
|
+
{
|
|
12242
|
+
a: 0,
|
|
12243
|
+
b: 4,
|
|
12244
|
+
w: 3
|
|
12245
|
+
},
|
|
12246
|
+
{
|
|
12247
|
+
a: 2,
|
|
12248
|
+
b: 3,
|
|
12249
|
+
w: 2
|
|
12250
|
+
},
|
|
12251
|
+
{
|
|
12252
|
+
a: 2,
|
|
12253
|
+
b: 5,
|
|
12254
|
+
w: 4
|
|
12255
|
+
},
|
|
12256
|
+
{
|
|
12257
|
+
a: 3,
|
|
12258
|
+
b: 4,
|
|
12259
|
+
w: 2
|
|
12260
|
+
},
|
|
12261
|
+
{
|
|
12262
|
+
a: 3,
|
|
12263
|
+
b: 6,
|
|
12264
|
+
w: 4
|
|
12265
|
+
},
|
|
12266
|
+
{
|
|
12267
|
+
a: 4,
|
|
12268
|
+
b: 7,
|
|
12269
|
+
w: 4
|
|
12270
|
+
},
|
|
12271
|
+
{
|
|
12272
|
+
a: 5,
|
|
12273
|
+
b: 6,
|
|
12274
|
+
w: 3
|
|
12275
|
+
},
|
|
12276
|
+
{
|
|
12277
|
+
a: 5,
|
|
12278
|
+
b: 8,
|
|
12279
|
+
w: 5
|
|
12280
|
+
},
|
|
12281
|
+
{
|
|
12282
|
+
a: 6,
|
|
12283
|
+
b: 7,
|
|
12284
|
+
w: 2
|
|
12285
|
+
},
|
|
12286
|
+
{
|
|
12287
|
+
a: 6,
|
|
12288
|
+
b: 1,
|
|
12289
|
+
w: 5
|
|
12290
|
+
},
|
|
12291
|
+
{
|
|
12292
|
+
a: 7,
|
|
12293
|
+
b: 1,
|
|
12294
|
+
w: 3
|
|
12295
|
+
},
|
|
12296
|
+
{
|
|
12297
|
+
a: 8,
|
|
12298
|
+
b: 1,
|
|
12299
|
+
w: 2
|
|
12300
|
+
}
|
|
12301
|
+
]
|
|
12302
|
+
}
|
|
12303
|
+
];
|
|
12304
|
+
/** Build a jittered grid mesh: cells at (col,row), edges between face-sharing neighbors. */
|
|
12305
|
+
function gridMesh(cols, rows, cellName, weightAt, jitter) {
|
|
12306
|
+
const nodes = [];
|
|
12307
|
+
const padX = 100 / (cols + 1);
|
|
12308
|
+
const padY = 100 / (rows + 1);
|
|
12309
|
+
for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) {
|
|
12310
|
+
const i = r * cols + c;
|
|
12311
|
+
const { dx, dy } = jitter(i);
|
|
12312
|
+
nodes.push({
|
|
12313
|
+
id: i,
|
|
12314
|
+
name: cellName(i),
|
|
12315
|
+
x: Math.round(padX * (c + 1) + dx),
|
|
12316
|
+
y: Math.round(padY * (r + 1) + dy)
|
|
12317
|
+
});
|
|
12318
|
+
}
|
|
12319
|
+
const edges = [];
|
|
12320
|
+
for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) {
|
|
12321
|
+
const i = r * cols + c;
|
|
12322
|
+
if (c + 1 < cols) edges.push({
|
|
12323
|
+
a: i,
|
|
12324
|
+
b: i + 1,
|
|
12325
|
+
w: weightAt(i, i + 1)
|
|
12326
|
+
});
|
|
12327
|
+
if (r + 1 < rows) edges.push({
|
|
12328
|
+
a: i,
|
|
12329
|
+
b: i + cols,
|
|
12330
|
+
w: weightAt(i, i + cols)
|
|
12331
|
+
});
|
|
12332
|
+
}
|
|
12333
|
+
return {
|
|
12334
|
+
nodes,
|
|
12335
|
+
edges
|
|
12336
|
+
};
|
|
12337
|
+
}
|
|
12338
|
+
const wobble = (i) => i * 7919 % 11 / 10 - .5;
|
|
12339
|
+
const plate = gridMesh(4, 3, (i) => `cell ${i}`, (a, b) => 1 + (a * 31 + b * 17) % 4, (i) => ({
|
|
12340
|
+
dx: wobble(i) * 6,
|
|
12341
|
+
dy: wobble(i + 3) * 6
|
|
12342
|
+
}));
|
|
12343
|
+
const reservoir = gridMesh(6, 3, (i) => `block ${i}`, (a, b) => 1 + (a * 13 + b * 29) % 5, (i) => ({
|
|
12344
|
+
dx: wobble(i + 1) * 8,
|
|
12345
|
+
dy: wobble(i + 5) * 8
|
|
12346
|
+
}));
|
|
12347
|
+
const blade = gridMesh(6, 4, (i) => `elem ${i}`, (a, b) => 1 + (a * 23 + b * 19) % 4, (i) => ({
|
|
12348
|
+
dx: wobble(i + 2) * 7,
|
|
12349
|
+
dy: wobble(i + 7) * 7
|
|
12350
|
+
}));
|
|
12351
|
+
const partitioningSampleProblems = [
|
|
12352
|
+
{
|
|
12353
|
+
family: "partitioning",
|
|
12354
|
+
name: "Cantilever Plate Mesh",
|
|
12355
|
+
description: "A 4×3 finite-element plate mesh split across two solver ranks. Edge weights are the face data exchanged every timestep — each cut edge is halo traffic both ranks pay forever. Classic balanced bisection, and small enough to race on the QAOA simulator in seconds.",
|
|
12356
|
+
nodes: plate.nodes,
|
|
12357
|
+
edges: plate.edges,
|
|
12358
|
+
k: 2,
|
|
12359
|
+
balanceTolerance: 1
|
|
12360
|
+
},
|
|
12361
|
+
{
|
|
12362
|
+
family: "partitioning",
|
|
12363
|
+
name: "Reservoir Grid Sectors",
|
|
12364
|
+
description: "An 18-block reservoir simulation grid decomposed across three compute nodes. The big version of this problem has billions of cells; the math of where to draw the seams is identical at every scale.",
|
|
12365
|
+
nodes: reservoir.nodes,
|
|
12366
|
+
edges: reservoir.edges,
|
|
12367
|
+
k: 3,
|
|
12368
|
+
balanceTolerance: 1
|
|
12369
|
+
},
|
|
12370
|
+
{
|
|
12371
|
+
family: "partitioning",
|
|
12372
|
+
name: "Turbine Blade Mesh",
|
|
12373
|
+
description: "A 24-element blade section spread over four solver ranks for a transient thermal run. Four-way splits punish lazy seams — every extra cut edge multiplies across thousands of timesteps.",
|
|
12374
|
+
nodes: blade.nodes,
|
|
12375
|
+
edges: blade.edges,
|
|
12376
|
+
k: 4,
|
|
12377
|
+
balanceTolerance: 1
|
|
12378
|
+
}
|
|
12379
|
+
];
|
|
12380
|
+
const selectionSampleProblems = [
|
|
12381
|
+
{
|
|
12382
|
+
family: "selection",
|
|
12383
|
+
name: "Indie Game Fund",
|
|
12384
|
+
description: "Twelve pitches, a $2M fund, and every project carries risk. Maximize expected portfolio value without betting the firm on moonshots.",
|
|
12385
|
+
budget: 200,
|
|
12386
|
+
riskWeight: 4,
|
|
12387
|
+
items: [
|
|
12388
|
+
{
|
|
12389
|
+
id: 0,
|
|
12390
|
+
name: "Cozy Farm Sim",
|
|
12391
|
+
value: 60,
|
|
12392
|
+
cost: 40,
|
|
12393
|
+
risk: 2
|
|
12394
|
+
},
|
|
12395
|
+
{
|
|
12396
|
+
id: 1,
|
|
12397
|
+
name: "Roguelike Deckbuilder",
|
|
12398
|
+
value: 85,
|
|
12399
|
+
cost: 55,
|
|
12400
|
+
risk: 4
|
|
12401
|
+
},
|
|
12402
|
+
{
|
|
12403
|
+
id: 2,
|
|
12404
|
+
name: "VR Escape Room",
|
|
12405
|
+
value: 95,
|
|
12406
|
+
cost: 70,
|
|
12407
|
+
risk: 8
|
|
12408
|
+
},
|
|
12409
|
+
{
|
|
12410
|
+
id: 3,
|
|
12411
|
+
name: "Pixel Metroidvania",
|
|
12412
|
+
value: 55,
|
|
12413
|
+
cost: 35,
|
|
12414
|
+
risk: 3
|
|
12415
|
+
},
|
|
12416
|
+
{
|
|
12417
|
+
id: 4,
|
|
12418
|
+
name: "MMO Sandbox",
|
|
12419
|
+
value: 160,
|
|
12420
|
+
cost: 120,
|
|
12421
|
+
risk: 10
|
|
12422
|
+
},
|
|
12423
|
+
{
|
|
12424
|
+
id: 5,
|
|
12425
|
+
name: "Mobile Puzzler",
|
|
12426
|
+
value: 35,
|
|
12427
|
+
cost: 18,
|
|
12428
|
+
risk: 1
|
|
12429
|
+
},
|
|
12430
|
+
{
|
|
12431
|
+
id: 6,
|
|
12432
|
+
name: "Co-op Heist Game",
|
|
12433
|
+
value: 75,
|
|
12434
|
+
cost: 50,
|
|
12435
|
+
risk: 5
|
|
12436
|
+
},
|
|
12437
|
+
{
|
|
12438
|
+
id: 7,
|
|
12439
|
+
name: "Narrative Adventure",
|
|
12440
|
+
value: 45,
|
|
12441
|
+
cost: 30,
|
|
12442
|
+
risk: 2
|
|
12443
|
+
},
|
|
12444
|
+
{
|
|
12445
|
+
id: 8,
|
|
12446
|
+
name: "Auto-Battler",
|
|
12447
|
+
value: 50,
|
|
12448
|
+
cost: 28,
|
|
12449
|
+
risk: 4
|
|
12450
|
+
},
|
|
12451
|
+
{
|
|
12452
|
+
id: 9,
|
|
12453
|
+
name: "Speedrun Platformer",
|
|
12454
|
+
value: 30,
|
|
12455
|
+
cost: 15,
|
|
12456
|
+
risk: 2
|
|
12457
|
+
},
|
|
12458
|
+
{
|
|
12459
|
+
id: 10,
|
|
12460
|
+
name: "City Builder",
|
|
12461
|
+
value: 90,
|
|
12462
|
+
cost: 65,
|
|
12463
|
+
risk: 5
|
|
12464
|
+
},
|
|
12465
|
+
{
|
|
12466
|
+
id: 11,
|
|
12467
|
+
name: "Horror Anthology",
|
|
12468
|
+
value: 40,
|
|
12469
|
+
cost: 25,
|
|
12470
|
+
risk: 6
|
|
12471
|
+
}
|
|
12472
|
+
]
|
|
12473
|
+
},
|
|
12474
|
+
{
|
|
12475
|
+
family: "selection",
|
|
12476
|
+
name: "Drone Sensor Loadout",
|
|
12477
|
+
description: "A recon drone has 48 units of payload mass. Pick the sensor suite that maximizes mission value — leave the gold-plated gear on the bench.",
|
|
12478
|
+
budget: 48,
|
|
12479
|
+
riskWeight: 0,
|
|
12480
|
+
items: [
|
|
12481
|
+
{
|
|
12482
|
+
id: 0,
|
|
12483
|
+
name: "EO Camera",
|
|
12484
|
+
value: 30,
|
|
12485
|
+
cost: 12
|
|
12486
|
+
},
|
|
12487
|
+
{
|
|
12488
|
+
id: 1,
|
|
12489
|
+
name: "IR Thermal",
|
|
12490
|
+
value: 28,
|
|
12491
|
+
cost: 10
|
|
12492
|
+
},
|
|
12493
|
+
{
|
|
12494
|
+
id: 2,
|
|
12495
|
+
name: "LIDAR",
|
|
12496
|
+
value: 35,
|
|
12497
|
+
cost: 18
|
|
12498
|
+
},
|
|
12499
|
+
{
|
|
12500
|
+
id: 3,
|
|
12501
|
+
name: "SIGINT Pod",
|
|
12502
|
+
value: 25,
|
|
12503
|
+
cost: 14
|
|
12504
|
+
},
|
|
12505
|
+
{
|
|
12506
|
+
id: 4,
|
|
12507
|
+
name: "Synthetic Aperture Radar",
|
|
12508
|
+
value: 40,
|
|
12509
|
+
cost: 22
|
|
12510
|
+
},
|
|
12511
|
+
{
|
|
12512
|
+
id: 5,
|
|
12513
|
+
name: "Laser Designator",
|
|
12514
|
+
value: 18,
|
|
12515
|
+
cost: 8
|
|
12516
|
+
},
|
|
12517
|
+
{
|
|
12518
|
+
id: 6,
|
|
12519
|
+
name: "Comms Relay",
|
|
12520
|
+
value: 15,
|
|
12521
|
+
cost: 6
|
|
12522
|
+
},
|
|
12523
|
+
{
|
|
12524
|
+
id: 7,
|
|
12525
|
+
name: "Magnetometer",
|
|
12526
|
+
value: 10,
|
|
12527
|
+
cost: 4
|
|
12528
|
+
},
|
|
12529
|
+
{
|
|
12530
|
+
id: 8,
|
|
12531
|
+
name: "Air Sampler",
|
|
12532
|
+
value: 8,
|
|
12533
|
+
cost: 5
|
|
12534
|
+
},
|
|
12535
|
+
{
|
|
12536
|
+
id: 9,
|
|
12537
|
+
name: "Spare Battery",
|
|
12538
|
+
value: 12,
|
|
12539
|
+
cost: 9
|
|
12540
|
+
}
|
|
12541
|
+
]
|
|
12542
|
+
},
|
|
12543
|
+
{
|
|
12544
|
+
family: "selection",
|
|
12545
|
+
name: "Feature Flag Quarter",
|
|
12546
|
+
description: "Fourteen engineering initiatives, 90 days of team capacity. Each carries delivery risk. Choose the roadmap that maximizes shipped value.",
|
|
12547
|
+
budget: 90,
|
|
12548
|
+
riskWeight: 3,
|
|
12549
|
+
items: [
|
|
12550
|
+
{
|
|
12551
|
+
id: 0,
|
|
12552
|
+
name: "Realtime Collab",
|
|
12553
|
+
value: 55,
|
|
12554
|
+
cost: 30,
|
|
12555
|
+
risk: 6
|
|
12556
|
+
},
|
|
12557
|
+
{
|
|
12558
|
+
id: 1,
|
|
12559
|
+
name: "Mobile Offline Mode",
|
|
12560
|
+
value: 40,
|
|
12561
|
+
cost: 25,
|
|
12562
|
+
risk: 4
|
|
12563
|
+
},
|
|
12564
|
+
{
|
|
12565
|
+
id: 2,
|
|
12566
|
+
name: "SSO Everywhere",
|
|
12567
|
+
value: 35,
|
|
12568
|
+
cost: 15,
|
|
12569
|
+
risk: 2
|
|
12570
|
+
},
|
|
12571
|
+
{
|
|
12572
|
+
id: 3,
|
|
12573
|
+
name: "Billing v2",
|
|
12574
|
+
value: 50,
|
|
12575
|
+
cost: 35,
|
|
12576
|
+
risk: 7
|
|
12577
|
+
},
|
|
12578
|
+
{
|
|
12579
|
+
id: 4,
|
|
12580
|
+
name: "AI Summaries",
|
|
12581
|
+
value: 45,
|
|
12582
|
+
cost: 20,
|
|
12583
|
+
risk: 3
|
|
12584
|
+
},
|
|
12585
|
+
{
|
|
12586
|
+
id: 5,
|
|
12587
|
+
name: "Audit Logs",
|
|
12588
|
+
value: 25,
|
|
12589
|
+
cost: 10,
|
|
12590
|
+
risk: 1
|
|
12591
|
+
},
|
|
12592
|
+
{
|
|
12593
|
+
id: 6,
|
|
12594
|
+
name: "Perf: Cold Start",
|
|
12595
|
+
value: 30,
|
|
12596
|
+
cost: 12,
|
|
12597
|
+
risk: 2
|
|
12598
|
+
},
|
|
12599
|
+
{
|
|
12600
|
+
id: 7,
|
|
12601
|
+
name: "Theme System",
|
|
12602
|
+
value: 15,
|
|
12603
|
+
cost: 8,
|
|
12604
|
+
risk: 1
|
|
12605
|
+
},
|
|
12606
|
+
{
|
|
12607
|
+
id: 8,
|
|
12608
|
+
name: "Webhooks v2",
|
|
12609
|
+
value: 28,
|
|
12610
|
+
cost: 14,
|
|
12611
|
+
risk: 3
|
|
12612
|
+
},
|
|
12613
|
+
{
|
|
12614
|
+
id: 9,
|
|
12615
|
+
name: "Data Residency",
|
|
12616
|
+
value: 38,
|
|
12617
|
+
cost: 28,
|
|
12618
|
+
risk: 5
|
|
12619
|
+
},
|
|
12620
|
+
{
|
|
12621
|
+
id: 10,
|
|
12622
|
+
name: "Search Rewrite",
|
|
12623
|
+
value: 42,
|
|
12624
|
+
cost: 26,
|
|
12625
|
+
risk: 5
|
|
12626
|
+
},
|
|
12627
|
+
{
|
|
12628
|
+
id: 11,
|
|
12629
|
+
name: "Onboarding Flow",
|
|
12630
|
+
value: 22,
|
|
12631
|
+
cost: 9,
|
|
12632
|
+
risk: 1
|
|
12633
|
+
},
|
|
12634
|
+
{
|
|
12635
|
+
id: 12,
|
|
12636
|
+
name: "Plugin SDK",
|
|
12637
|
+
value: 48,
|
|
12638
|
+
cost: 32,
|
|
12639
|
+
risk: 6
|
|
12640
|
+
},
|
|
12641
|
+
{
|
|
12642
|
+
id: 13,
|
|
12643
|
+
name: "A11y Sweep",
|
|
12644
|
+
value: 20,
|
|
12645
|
+
cost: 11,
|
|
12646
|
+
risk: 1
|
|
12647
|
+
}
|
|
12648
|
+
]
|
|
12649
|
+
}
|
|
12650
|
+
];
|
|
12651
|
+
const economicSampleProblems = [
|
|
12652
|
+
{
|
|
12653
|
+
family: "economic",
|
|
12654
|
+
name: "Spectrum Auction",
|
|
12655
|
+
description: "Five regional spectrum licenses, nine carriers bidding on bundles. Sell each license once, maximize treasury revenue — the classic FCC winner-determination problem.",
|
|
12656
|
+
goods: [
|
|
12657
|
+
{
|
|
12658
|
+
id: 0,
|
|
12659
|
+
name: "North Band"
|
|
12660
|
+
},
|
|
12661
|
+
{
|
|
12662
|
+
id: 1,
|
|
12663
|
+
name: "South Band"
|
|
12664
|
+
},
|
|
12665
|
+
{
|
|
12666
|
+
id: 2,
|
|
12667
|
+
name: "East Band"
|
|
12668
|
+
},
|
|
12669
|
+
{
|
|
12670
|
+
id: 3,
|
|
12671
|
+
name: "West Band"
|
|
12672
|
+
},
|
|
12673
|
+
{
|
|
12674
|
+
id: 4,
|
|
12675
|
+
name: "Metro Core"
|
|
12676
|
+
}
|
|
12677
|
+
],
|
|
12678
|
+
bids: [
|
|
12679
|
+
{
|
|
12680
|
+
id: 0,
|
|
12681
|
+
bidder: "AstraTel",
|
|
12682
|
+
price: 120,
|
|
12683
|
+
goodIds: [0, 4]
|
|
12684
|
+
},
|
|
12685
|
+
{
|
|
12686
|
+
id: 1,
|
|
12687
|
+
bidder: "AstraTel",
|
|
12688
|
+
price: 60,
|
|
12689
|
+
goodIds: [0]
|
|
12690
|
+
},
|
|
12691
|
+
{
|
|
12692
|
+
id: 2,
|
|
12693
|
+
bidder: "Borealis",
|
|
12694
|
+
price: 140,
|
|
12695
|
+
goodIds: [1, 2]
|
|
12696
|
+
},
|
|
12697
|
+
{
|
|
12698
|
+
id: 3,
|
|
12699
|
+
bidder: "Borealis",
|
|
12700
|
+
price: 65,
|
|
12701
|
+
goodIds: [1]
|
|
12702
|
+
},
|
|
12703
|
+
{
|
|
12704
|
+
id: 4,
|
|
12705
|
+
bidder: "CometNet",
|
|
12706
|
+
price: 95,
|
|
12707
|
+
goodIds: [2, 3]
|
|
12708
|
+
},
|
|
12709
|
+
{
|
|
12710
|
+
id: 5,
|
|
12711
|
+
bidder: "CometNet",
|
|
12712
|
+
price: 50,
|
|
12713
|
+
goodIds: [3]
|
|
12714
|
+
},
|
|
12715
|
+
{
|
|
12716
|
+
id: 6,
|
|
12717
|
+
bidder: "DyneMobile",
|
|
12718
|
+
price: 180,
|
|
12719
|
+
goodIds: [
|
|
12720
|
+
0,
|
|
12721
|
+
1,
|
|
12722
|
+
4
|
|
12723
|
+
]
|
|
12724
|
+
},
|
|
12725
|
+
{
|
|
12726
|
+
id: 7,
|
|
12727
|
+
bidder: "Equinox",
|
|
12728
|
+
price: 75,
|
|
12729
|
+
goodIds: [4]
|
|
12730
|
+
},
|
|
12731
|
+
{
|
|
12732
|
+
id: 8,
|
|
12733
|
+
bidder: "Equinox",
|
|
12734
|
+
price: 110,
|
|
12735
|
+
goodIds: [2, 4]
|
|
12736
|
+
}
|
|
12737
|
+
]
|
|
12738
|
+
},
|
|
12739
|
+
{
|
|
12740
|
+
family: "economic",
|
|
12741
|
+
name: "Cloud Spot Market",
|
|
12742
|
+
description: "Six GPU node pools, ten batch workloads bidding for exclusive overnight windows. Maximize the operator's take across all-or-nothing reservations.",
|
|
12743
|
+
goods: [
|
|
12744
|
+
{
|
|
12745
|
+
id: 0,
|
|
12746
|
+
name: "A100 Pool 1"
|
|
12747
|
+
},
|
|
12748
|
+
{
|
|
12749
|
+
id: 1,
|
|
12750
|
+
name: "A100 Pool 2"
|
|
12751
|
+
},
|
|
12752
|
+
{
|
|
12753
|
+
id: 2,
|
|
12754
|
+
name: "H100 Pool 1"
|
|
12755
|
+
},
|
|
12756
|
+
{
|
|
12757
|
+
id: 3,
|
|
12758
|
+
name: "H100 Pool 2"
|
|
12759
|
+
},
|
|
12760
|
+
{
|
|
12761
|
+
id: 4,
|
|
12762
|
+
name: "TPU Pod"
|
|
12763
|
+
},
|
|
12764
|
+
{
|
|
12765
|
+
id: 5,
|
|
12766
|
+
name: "CPU Farm"
|
|
12767
|
+
}
|
|
12768
|
+
],
|
|
12769
|
+
bids: [
|
|
12770
|
+
{
|
|
12771
|
+
id: 0,
|
|
12772
|
+
bidder: "BioFold Labs",
|
|
12773
|
+
price: 90,
|
|
12774
|
+
goodIds: [2, 3]
|
|
12775
|
+
},
|
|
12776
|
+
{
|
|
12777
|
+
id: 1,
|
|
12778
|
+
bidder: "BioFold Labs",
|
|
12779
|
+
price: 48,
|
|
12780
|
+
goodIds: [2]
|
|
12781
|
+
},
|
|
12782
|
+
{
|
|
12783
|
+
id: 2,
|
|
12784
|
+
bidder: "RenderWorks",
|
|
12785
|
+
price: 55,
|
|
12786
|
+
goodIds: [0, 1]
|
|
12787
|
+
},
|
|
12788
|
+
{
|
|
12789
|
+
id: 3,
|
|
12790
|
+
bidder: "RenderWorks",
|
|
12791
|
+
price: 30,
|
|
12792
|
+
goodIds: [0]
|
|
12793
|
+
},
|
|
12794
|
+
{
|
|
12795
|
+
id: 4,
|
|
12796
|
+
bidder: "LLM Foundry",
|
|
12797
|
+
price: 130,
|
|
12798
|
+
goodIds: [
|
|
12799
|
+
2,
|
|
12800
|
+
3,
|
|
12801
|
+
4
|
|
12802
|
+
]
|
|
12803
|
+
},
|
|
12804
|
+
{
|
|
12805
|
+
id: 5,
|
|
12806
|
+
bidder: "LLM Foundry",
|
|
12807
|
+
price: 70,
|
|
12808
|
+
goodIds: [4]
|
|
12809
|
+
},
|
|
12810
|
+
{
|
|
12811
|
+
id: 6,
|
|
12812
|
+
bidder: "QuantSim",
|
|
12813
|
+
price: 42,
|
|
12814
|
+
goodIds: [1, 5]
|
|
12815
|
+
},
|
|
12816
|
+
{
|
|
12817
|
+
id: 7,
|
|
12818
|
+
bidder: "QuantSim",
|
|
12819
|
+
price: 22,
|
|
12820
|
+
goodIds: [5]
|
|
12821
|
+
},
|
|
12822
|
+
{
|
|
12823
|
+
id: 8,
|
|
12824
|
+
bidder: "WeatherNet",
|
|
12825
|
+
price: 65,
|
|
12826
|
+
goodIds: [0, 5]
|
|
12827
|
+
},
|
|
12828
|
+
{
|
|
12829
|
+
id: 9,
|
|
12830
|
+
bidder: "GenomeScan",
|
|
12831
|
+
price: 38,
|
|
12832
|
+
goodIds: [1]
|
|
12833
|
+
}
|
|
12834
|
+
]
|
|
12835
|
+
},
|
|
12836
|
+
{
|
|
12837
|
+
family: "economic",
|
|
12838
|
+
name: "Stadium Sponsorship Bundle",
|
|
12839
|
+
description: "Seven sponsorship assets — naming rights, jersey patch, tunnel club — and eight brands bidding on combinations. One sale per asset; maximize the franchise's deal sheet.",
|
|
12840
|
+
goods: [
|
|
12841
|
+
{
|
|
12842
|
+
id: 0,
|
|
12843
|
+
name: "Naming Rights"
|
|
12844
|
+
},
|
|
12845
|
+
{
|
|
12846
|
+
id: 1,
|
|
12847
|
+
name: "Jersey Patch"
|
|
12848
|
+
},
|
|
12849
|
+
{
|
|
12850
|
+
id: 2,
|
|
12851
|
+
name: "Tunnel Club"
|
|
12852
|
+
},
|
|
12853
|
+
{
|
|
12854
|
+
id: 3,
|
|
12855
|
+
name: "Scoreboard"
|
|
12856
|
+
},
|
|
12857
|
+
{
|
|
12858
|
+
id: 4,
|
|
12859
|
+
name: "Practice Facility"
|
|
12860
|
+
},
|
|
12861
|
+
{
|
|
12862
|
+
id: 5,
|
|
12863
|
+
name: "Beer Pouring Rights"
|
|
12864
|
+
},
|
|
12865
|
+
{
|
|
12866
|
+
id: 6,
|
|
12867
|
+
name: "Halftime Show"
|
|
12868
|
+
}
|
|
12869
|
+
],
|
|
12870
|
+
bids: [
|
|
12871
|
+
{
|
|
12872
|
+
id: 0,
|
|
12873
|
+
bidder: "Vertex Air",
|
|
12874
|
+
price: 200,
|
|
12875
|
+
goodIds: [0, 3]
|
|
12876
|
+
},
|
|
12877
|
+
{
|
|
12878
|
+
id: 1,
|
|
12879
|
+
bidder: "Vertex Air",
|
|
12880
|
+
price: 130,
|
|
12881
|
+
goodIds: [0]
|
|
12882
|
+
},
|
|
12883
|
+
{
|
|
12884
|
+
id: 2,
|
|
12885
|
+
bidder: "Cascade Beer",
|
|
12886
|
+
price: 85,
|
|
12887
|
+
goodIds: [5, 6]
|
|
12888
|
+
},
|
|
12889
|
+
{
|
|
12890
|
+
id: 3,
|
|
12891
|
+
bidder: "Cascade Beer",
|
|
12892
|
+
price: 55,
|
|
12893
|
+
goodIds: [5]
|
|
12894
|
+
},
|
|
12895
|
+
{
|
|
12896
|
+
id: 4,
|
|
12897
|
+
bidder: "NovaBank",
|
|
12898
|
+
price: 150,
|
|
12899
|
+
goodIds: [1, 2]
|
|
12900
|
+
},
|
|
12901
|
+
{
|
|
12902
|
+
id: 5,
|
|
12903
|
+
bidder: "NovaBank",
|
|
12904
|
+
price: 80,
|
|
12905
|
+
goodIds: [1]
|
|
12906
|
+
},
|
|
12907
|
+
{
|
|
12908
|
+
id: 6,
|
|
12909
|
+
bidder: "GrindHouse Coffee",
|
|
12910
|
+
price: 45,
|
|
12911
|
+
goodIds: [2]
|
|
12912
|
+
},
|
|
12913
|
+
{
|
|
12914
|
+
id: 7,
|
|
12915
|
+
bidder: "Pixel Motors",
|
|
12916
|
+
price: 110,
|
|
12917
|
+
goodIds: [3, 4]
|
|
12918
|
+
},
|
|
12919
|
+
{
|
|
12920
|
+
id: 8,
|
|
12921
|
+
bidder: "Pixel Motors",
|
|
12922
|
+
price: 60,
|
|
12923
|
+
goodIds: [4]
|
|
12924
|
+
},
|
|
12925
|
+
{
|
|
12926
|
+
id: 9,
|
|
12927
|
+
bidder: "StreamCo",
|
|
12928
|
+
price: 70,
|
|
12929
|
+
goodIds: [6]
|
|
12930
|
+
}
|
|
12931
|
+
]
|
|
10918
12932
|
}
|
|
10919
|
-
|
|
10920
|
-
|
|
10921
|
-
|
|
10922
|
-
|
|
10923
|
-
|
|
10924
|
-
|
|
10925
|
-
|
|
10926
|
-
|
|
10927
|
-
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
|
|
10931
|
-
|
|
12933
|
+
];
|
|
12934
|
+
const continuousSampleProblems = [
|
|
12935
|
+
{
|
|
12936
|
+
family: "continuous",
|
|
12937
|
+
name: "Reactor Temperature Tuning",
|
|
12938
|
+
description: "One control dial, a yield curve full of local sweet spots, and exactly one true optimum. The wavy bowl eats naive hill climbers for breakfast.",
|
|
12939
|
+
functionId: "wavy-bowl",
|
|
12940
|
+
dims: 1,
|
|
12941
|
+
lo: -10,
|
|
12942
|
+
hi: 10,
|
|
12943
|
+
paramNames: ["temperature offset"]
|
|
12944
|
+
},
|
|
12945
|
+
{
|
|
12946
|
+
family: "continuous",
|
|
12947
|
+
name: "Antenna Sweet Spot",
|
|
12948
|
+
description: "Two placement coordinates on the roof; signal interference makes four equally good mounting points. Himmelblau's function — which optimum will your solver find?",
|
|
12949
|
+
functionId: "himmelblau",
|
|
12950
|
+
dims: 2,
|
|
12951
|
+
lo: -6,
|
|
12952
|
+
hi: 6,
|
|
12953
|
+
paramNames: ["east-west", "north-south"]
|
|
12954
|
+
},
|
|
12955
|
+
{
|
|
12956
|
+
family: "continuous",
|
|
12957
|
+
name: "Hyperparameter Canyon",
|
|
12958
|
+
description: "Two training knobs over a Rastrigin egg-carton — dozens of local minima arranged in a lattice, one global floor at the origin. Pure trap density.",
|
|
12959
|
+
functionId: "rastrigin",
|
|
12960
|
+
dims: 2,
|
|
12961
|
+
lo: -5.12,
|
|
12962
|
+
hi: 5.12,
|
|
12963
|
+
paramNames: ["learning rate (scaled)", "regularization (scaled)"]
|
|
10932
12964
|
}
|
|
10933
|
-
|
|
10934
|
-
nodes,
|
|
10935
|
-
edges
|
|
10936
|
-
};
|
|
10937
|
-
}
|
|
10938
|
-
const wobble = (i) => i * 7919 % 11 / 10 - .5;
|
|
10939
|
-
const plate = gridMesh(4, 3, (i) => `cell ${i}`, (a, b) => 1 + (a * 31 + b * 17) % 4, (i) => ({
|
|
10940
|
-
dx: wobble(i) * 6,
|
|
10941
|
-
dy: wobble(i + 3) * 6
|
|
10942
|
-
}));
|
|
10943
|
-
const reservoir = gridMesh(6, 3, (i) => `block ${i}`, (a, b) => 1 + (a * 13 + b * 29) % 5, (i) => ({
|
|
10944
|
-
dx: wobble(i + 1) * 8,
|
|
10945
|
-
dy: wobble(i + 5) * 8
|
|
10946
|
-
}));
|
|
10947
|
-
const blade = gridMesh(6, 4, (i) => `elem ${i}`, (a, b) => 1 + (a * 23 + b * 19) % 4, (i) => ({
|
|
10948
|
-
dx: wobble(i + 2) * 7,
|
|
10949
|
-
dy: wobble(i + 7) * 7
|
|
10950
|
-
}));
|
|
10951
|
-
plate.nodes, plate.edges, reservoir.nodes, reservoir.edges, blade.nodes, blade.edges;
|
|
12965
|
+
];
|
|
10952
12966
|
var QuboBuilder = class {
|
|
10953
12967
|
size;
|
|
10954
12968
|
q = /* @__PURE__ */ new Map();
|
|
@@ -11280,8 +13294,270 @@ function continuousToy() {
|
|
|
11280
13294
|
};
|
|
11281
13295
|
}
|
|
11282
13296
|
schedulingToy(), routingToy(), packingToy(), assignmentToy(), networkToy(), partitioningToy(), selectionToy(), economicToy(), continuousToy();
|
|
13297
|
+
/**
|
|
13298
|
+
* Per-family problem Zod schemas — the validation foundation for custom problem
|
|
13299
|
+
* EDITING (FamilyProblemEditor validates JSON against these) and LLM FORMULATION
|
|
13300
|
+
* (quantum_formulate validates the model's output before surfacing it).
|
|
13301
|
+
*
|
|
13302
|
+
* Authored to match the hand-written interfaces in `./types`; a type-level check
|
|
13303
|
+
* at the bottom keeps the two in sync. The family discriminant lets a single
|
|
13304
|
+
* editor/tool dispatch across all eight shapes.
|
|
13305
|
+
*/
|
|
13306
|
+
const named = {
|
|
13307
|
+
id: z.number().int(),
|
|
13308
|
+
name: z.string().min(1)
|
|
13309
|
+
};
|
|
13310
|
+
const xy = {
|
|
13311
|
+
x: z.number(),
|
|
13312
|
+
y: z.number()
|
|
13313
|
+
};
|
|
13314
|
+
const edge = z.object({
|
|
13315
|
+
a: z.number().int().nonnegative(),
|
|
13316
|
+
b: z.number().int().nonnegative(),
|
|
13317
|
+
w: z.number().optional()
|
|
13318
|
+
});
|
|
13319
|
+
const RoutingProblemSchema = z.object({
|
|
13320
|
+
family: z.literal("routing"),
|
|
13321
|
+
name: z.string().min(1),
|
|
13322
|
+
description: z.string().optional(),
|
|
13323
|
+
nodes: z.array(z.object({
|
|
13324
|
+
...named,
|
|
13325
|
+
...xy
|
|
13326
|
+
})).min(2)
|
|
13327
|
+
});
|
|
13328
|
+
const PackingProblemSchema = z.object({
|
|
13329
|
+
family: z.literal("packing"),
|
|
13330
|
+
name: z.string().min(1),
|
|
13331
|
+
description: z.string().optional(),
|
|
13332
|
+
items: z.array(z.object({
|
|
13333
|
+
...named,
|
|
13334
|
+
size: z.number().positive()
|
|
13335
|
+
})).min(1),
|
|
13336
|
+
binCapacity: z.number().positive(),
|
|
13337
|
+
binLabel: z.string().min(1)
|
|
13338
|
+
});
|
|
13339
|
+
const AssignmentProblemSchema = z.object({
|
|
13340
|
+
family: z.literal("assignment"),
|
|
13341
|
+
name: z.string().min(1),
|
|
13342
|
+
description: z.string().optional(),
|
|
13343
|
+
agents: z.array(z.object(named)).min(1),
|
|
13344
|
+
tasks: z.array(z.object(named)).min(1),
|
|
13345
|
+
cost: z.array(z.array(z.number())).min(1)
|
|
13346
|
+
});
|
|
13347
|
+
const NetworkProblemSchema = z.object({
|
|
13348
|
+
family: z.literal("network"),
|
|
13349
|
+
name: z.string().min(1),
|
|
13350
|
+
description: z.string().optional(),
|
|
13351
|
+
nodes: z.array(z.object({
|
|
13352
|
+
...named,
|
|
13353
|
+
...xy
|
|
13354
|
+
})).min(1),
|
|
13355
|
+
edges: z.array(edge)
|
|
13356
|
+
});
|
|
13357
|
+
const PartitionProblemSchema = z.object({
|
|
13358
|
+
family: z.literal("partitioning"),
|
|
13359
|
+
name: z.string().min(1),
|
|
13360
|
+
description: z.string().optional(),
|
|
13361
|
+
nodes: z.array(z.object({
|
|
13362
|
+
...named,
|
|
13363
|
+
...xy
|
|
13364
|
+
})).min(1),
|
|
13365
|
+
edges: z.array(edge),
|
|
13366
|
+
k: z.number().int().min(2),
|
|
13367
|
+
balanceTolerance: z.number().int().nonnegative().optional()
|
|
13368
|
+
});
|
|
13369
|
+
const SelectionProblemSchema = z.object({
|
|
13370
|
+
family: z.literal("selection"),
|
|
13371
|
+
name: z.string().min(1),
|
|
13372
|
+
description: z.string().optional(),
|
|
13373
|
+
items: z.array(z.object({
|
|
13374
|
+
...named,
|
|
13375
|
+
value: z.number(),
|
|
13376
|
+
cost: z.number().positive(),
|
|
13377
|
+
risk: z.number().optional()
|
|
13378
|
+
})).min(1),
|
|
13379
|
+
budget: z.number().positive(),
|
|
13380
|
+
riskWeight: z.number().optional()
|
|
13381
|
+
});
|
|
13382
|
+
const EconomicProblemSchema = z.object({
|
|
13383
|
+
family: z.literal("economic"),
|
|
13384
|
+
name: z.string().min(1),
|
|
13385
|
+
description: z.string().optional(),
|
|
13386
|
+
goods: z.array(z.object(named)).min(1),
|
|
13387
|
+
bids: z.array(z.object({
|
|
13388
|
+
id: z.number().int(),
|
|
13389
|
+
bidder: z.string().min(1),
|
|
13390
|
+
price: z.number(),
|
|
13391
|
+
goodIds: z.array(z.number().int().nonnegative())
|
|
13392
|
+
})).min(1)
|
|
13393
|
+
});
|
|
13394
|
+
const ContinuousProblemSchema = z.object({
|
|
13395
|
+
family: z.literal("continuous"),
|
|
13396
|
+
name: z.string().min(1),
|
|
13397
|
+
description: z.string().optional(),
|
|
13398
|
+
functionId: z.enum([
|
|
13399
|
+
"rastrigin",
|
|
13400
|
+
"ackley",
|
|
13401
|
+
"himmelblau",
|
|
13402
|
+
"wavy-bowl"
|
|
13403
|
+
]),
|
|
13404
|
+
dims: z.union([z.literal(1), z.literal(2)]),
|
|
13405
|
+
lo: z.number(),
|
|
13406
|
+
hi: z.number(),
|
|
13407
|
+
paramNames: z.array(z.string())
|
|
13408
|
+
});
|
|
13409
|
+
z.discriminatedUnion("family", [
|
|
13410
|
+
RoutingProblemSchema,
|
|
13411
|
+
PackingProblemSchema,
|
|
13412
|
+
AssignmentProblemSchema,
|
|
13413
|
+
NetworkProblemSchema,
|
|
13414
|
+
PartitionProblemSchema,
|
|
13415
|
+
SelectionProblemSchema,
|
|
13416
|
+
EconomicProblemSchema,
|
|
13417
|
+
ContinuousProblemSchema
|
|
13418
|
+
]);
|
|
13419
|
+
const refineAssignment = (p, ctx) => {
|
|
13420
|
+
if (p.cost.length !== p.agents.length) ctx.addIssue({
|
|
13421
|
+
code: z.ZodIssueCode.custom,
|
|
13422
|
+
path: ["cost"],
|
|
13423
|
+
message: `cost must have one row per agent (${p.agents.length}); got ${p.cost.length}`
|
|
13424
|
+
});
|
|
13425
|
+
p.cost.forEach((row, i) => {
|
|
13426
|
+
if (row.length !== p.tasks.length) ctx.addIssue({
|
|
13427
|
+
code: z.ZodIssueCode.custom,
|
|
13428
|
+
path: ["cost", i],
|
|
13429
|
+
message: `cost row ${i} must have one column per task (${p.tasks.length}); got ${row.length}`
|
|
13430
|
+
});
|
|
13431
|
+
});
|
|
13432
|
+
};
|
|
13433
|
+
const refineEdgeBounds = (p, ctx) => {
|
|
13434
|
+
const n = p.nodes.length;
|
|
13435
|
+
p.edges.forEach((e, i) => {
|
|
13436
|
+
if (e.a >= n || e.b >= n) ctx.addIssue({
|
|
13437
|
+
code: z.ZodIssueCode.custom,
|
|
13438
|
+
path: ["edges", i],
|
|
13439
|
+
message: `edge endpoints must reference nodes 0..${n - 1}; got a=${e.a}, b=${e.b}`
|
|
13440
|
+
});
|
|
13441
|
+
});
|
|
13442
|
+
};
|
|
13443
|
+
const refineEconomic = (p, ctx) => {
|
|
13444
|
+
const n = p.goods.length;
|
|
13445
|
+
p.bids.forEach((bid, i) => {
|
|
13446
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13447
|
+
bid.goodIds.forEach((g, j) => {
|
|
13448
|
+
if (g >= n) ctx.addIssue({
|
|
13449
|
+
code: z.ZodIssueCode.custom,
|
|
13450
|
+
path: [
|
|
13451
|
+
"bids",
|
|
13452
|
+
i,
|
|
13453
|
+
"goodIds",
|
|
13454
|
+
j
|
|
13455
|
+
],
|
|
13456
|
+
message: `goodId must reference goods 0..${n - 1}; got ${g}`
|
|
13457
|
+
});
|
|
13458
|
+
if (seen.has(g)) ctx.addIssue({
|
|
13459
|
+
code: z.ZodIssueCode.custom,
|
|
13460
|
+
path: [
|
|
13461
|
+
"bids",
|
|
13462
|
+
i,
|
|
13463
|
+
"goodIds",
|
|
13464
|
+
j
|
|
13465
|
+
],
|
|
13466
|
+
message: `duplicate goodId ${g} in bid ${i}`
|
|
13467
|
+
});
|
|
13468
|
+
seen.add(g);
|
|
13469
|
+
});
|
|
13470
|
+
});
|
|
13471
|
+
};
|
|
13472
|
+
/** Per-family schema lookup — the editor/tool pick the right one by familyId. */
|
|
13473
|
+
const FAMILY_PROBLEM_SCHEMAS = {
|
|
13474
|
+
routing: RoutingProblemSchema,
|
|
13475
|
+
packing: PackingProblemSchema,
|
|
13476
|
+
assignment: AssignmentProblemSchema.superRefine(refineAssignment),
|
|
13477
|
+
network: NetworkProblemSchema.superRefine(refineEdgeBounds),
|
|
13478
|
+
partitioning: PartitionProblemSchema.superRefine(refineEdgeBounds),
|
|
13479
|
+
selection: SelectionProblemSchema,
|
|
13480
|
+
economic: EconomicProblemSchema.superRefine(refineEconomic),
|
|
13481
|
+
continuous: ContinuousProblemSchema
|
|
13482
|
+
};
|
|
13483
|
+
const FAMILY_SAMPLE_PROBLEMS = {
|
|
13484
|
+
routing: routingSampleProblems,
|
|
13485
|
+
packing: packingSampleProblems,
|
|
13486
|
+
assignment: assignmentSampleProblems,
|
|
13487
|
+
network: networkSampleProblems,
|
|
13488
|
+
partitioning: partitioningSampleProblems,
|
|
13489
|
+
selection: selectionSampleProblems,
|
|
13490
|
+
economic: economicSampleProblems,
|
|
13491
|
+
continuous: continuousSampleProblems
|
|
13492
|
+
};
|
|
11283
13493
|
//#endregion
|
|
11284
|
-
//#region ../../b4m-core/services/dist/tools-
|
|
13494
|
+
//#region ../../b4m-core/services/dist/tools-BhiSgg5-.mjs
|
|
13495
|
+
const createFabFileSchema = z.object({
|
|
13496
|
+
fileName: z.string(),
|
|
13497
|
+
mimeType: z.string(),
|
|
13498
|
+
fileSize: z.number(),
|
|
13499
|
+
type: z.enum(KnowledgeType),
|
|
13500
|
+
content: z.union([z.string(), z.instanceof(Buffer)]).optional(),
|
|
13501
|
+
organizationId: z.string().optional(),
|
|
13502
|
+
/**
|
|
13503
|
+
* Content type of the file
|
|
13504
|
+
* @example 'text/markdown'
|
|
13505
|
+
* @example 'application/pdf'
|
|
13506
|
+
* @example 'application/octet-stream' for binary files
|
|
13507
|
+
*/
|
|
13508
|
+
contentType: z.string().optional(),
|
|
13509
|
+
public: z.boolean().optional(),
|
|
13510
|
+
prefix: z.string().optional(),
|
|
13511
|
+
system: z.boolean().optional(),
|
|
13512
|
+
tags: z.array(z.object({
|
|
13513
|
+
name: z.string(),
|
|
13514
|
+
strength: z.number()
|
|
13515
|
+
})).optional(),
|
|
13516
|
+
systemPriority: z.number().optional(),
|
|
13517
|
+
sessionId: z.string().optional(),
|
|
13518
|
+
contentHash: z.string().optional(),
|
|
13519
|
+
batchId: z.string().optional(),
|
|
13520
|
+
relativePath: z.string().optional()
|
|
13521
|
+
});
|
|
13522
|
+
const DEFAULT_MAX_FILE_SIZE = 20;
|
|
13523
|
+
const DEFAULT_EXPIRE_IN_SECONDS = 3600 * 24 * 5;
|
|
13524
|
+
const createFabFile = async (userId, parameters, { db, storage }) => {
|
|
13525
|
+
const params = secureParameters(parameters, createFabFileSchema);
|
|
13526
|
+
const user = await db.users.findById(userId);
|
|
13527
|
+
if (!user) throw new BadRequestError("User not found");
|
|
13528
|
+
let ext = "";
|
|
13529
|
+
let mimeType = parameters.mimeType;
|
|
13530
|
+
ext = getFileExtension(params.fileName);
|
|
13531
|
+
mimeType = params.mimeType || getMimeTypeByExtension(ext);
|
|
13532
|
+
if (!mimeType) mimeType = SupportedFabFileMimeTypes.TXT_PLAIN;
|
|
13533
|
+
if (!Object.values(SupportedFabFileMimeTypes).some((type) => type === mimeType)) throw new BadRequestError(`File type ${mimeType} is not supported`);
|
|
13534
|
+
let filePath = params.prefix ? `${params.prefix}/` : "";
|
|
13535
|
+
filePath += `${v4()}${ext ? `.${ext}` : ".txt"}`;
|
|
13536
|
+
const maxFileSize = getSettingsValue("MaxFileSize", await getSettingsMap(db), DEFAULT_MAX_FILE_SIZE) * 1024 * 1024;
|
|
13537
|
+
if (params.fileSize >= maxFileSize) throw new BadRequestError("File size exceeds maximum file size");
|
|
13538
|
+
await checkStorageLimitForFile(user, params.fileSize, params.organizationId, db.organizations?.findById);
|
|
13539
|
+
const buildData = {
|
|
13540
|
+
userId,
|
|
13541
|
+
...params,
|
|
13542
|
+
mimeType,
|
|
13543
|
+
filePath,
|
|
13544
|
+
users: [],
|
|
13545
|
+
groups: [],
|
|
13546
|
+
isGlobalRead: false,
|
|
13547
|
+
isGlobalWrite: false,
|
|
13548
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
13549
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
13550
|
+
};
|
|
13551
|
+
if (params.content) {
|
|
13552
|
+
await storage.upload(filePath, params.content, {
|
|
13553
|
+
ContentType: params.contentType,
|
|
13554
|
+
ContentLength: params.fileSize
|
|
13555
|
+
});
|
|
13556
|
+
buildData.fileUrl = await storage.generateSignedUrl(filePath, DEFAULT_EXPIRE_IN_SECONDS, "get");
|
|
13557
|
+
buildData.fileUrlExpireAt = new Date(Date.now() + DEFAULT_EXPIRE_IN_SECONDS * 1e3);
|
|
13558
|
+
} else buildData.presignedUrl = await storage.generateSignedUrl(filePath, 600, "put");
|
|
13559
|
+
return await db.fabFiles.create(buildData);
|
|
13560
|
+
};
|
|
11285
13561
|
async function performDeepResearch(context, params, config = {}) {
|
|
11286
13562
|
const maxDepth = config.maxDepth || 7;
|
|
11287
13563
|
const duration = config.duration || 4.5;
|
|
@@ -11642,9 +13918,10 @@ const deepResearchTool = {
|
|
|
11642
13918
|
async function getDynamicDataLakeAccess(context) {
|
|
11643
13919
|
const userTags = context.user.tags || [];
|
|
11644
13920
|
const entitlementKeys = context.entitlementKeys ?? [];
|
|
13921
|
+
const organizationId = context.user.organizationId ? String(context.user.organizationId) : void 0;
|
|
11645
13922
|
let dynamicDataLakes;
|
|
11646
13923
|
if (context.db.dataLakes) try {
|
|
11647
|
-
dynamicDataLakes = (await context.db.dataLakes.findActiveByUserTagsAndEntitlements(userTags, entitlementKeys)).map(toDataLakeConfig);
|
|
13924
|
+
dynamicDataLakes = (await context.db.dataLakes.findActiveByUserTagsAndEntitlements(userTags, entitlementKeys, organizationId)).map(toDataLakeConfig);
|
|
11648
13925
|
} catch {}
|
|
11649
13926
|
const accessibleLakes = getAccessibleDataLakes(userTags, dynamicDataLakes, entitlementKeys);
|
|
11650
13927
|
return {
|
|
@@ -11792,6 +14069,60 @@ const weatherTool = {
|
|
|
11792
14069
|
}
|
|
11793
14070
|
})
|
|
11794
14071
|
};
|
|
14072
|
+
/**
|
|
14073
|
+
* Persist a tool-generated file (image, Excel, etc.) as a session-scoped FabFile so it
|
|
14074
|
+
* shows up in the Knowledge Base / WorkBench and is downloadable after the run.
|
|
14075
|
+
*
|
|
14076
|
+
* Why this exists: file-generating tools historically only pushed the generated filename
|
|
14077
|
+
* into `quest.images` via `statusUpdate`, which (a) renders fine inline for images but is
|
|
14078
|
+
* a broken `<img>` for non-image files like .xlsx, and (b) was never recorded as a FabFile,
|
|
14079
|
+
* so nothing the user can browse referenced it — the file was effectively orphaned in the
|
|
14080
|
+
* generated-content bucket (see prod session 6a41abae…, where 4 agent-generated images were
|
|
14081
|
+
* lost entirely). Creating a FabFile with `sessionId` set makes the file appear in the
|
|
14082
|
+
* Knowledge Viewer via `useGetFabFilesBySessionId` → `useMessageFiles`.
|
|
14083
|
+
*
|
|
14084
|
+
* Best-effort: a failure here (missing adapters, storage quota, unsupported mime) must never
|
|
14085
|
+
* break the tool itself — the inline `quest.images` render still works. We log and swallow.
|
|
14086
|
+
*
|
|
14087
|
+
* The file is re-uploaded into the FabFile bucket (`context.storage`) because the Knowledge
|
|
14088
|
+
* Viewer reads FabFiles through their signed `fileUrl`, which is issued against that bucket.
|
|
14089
|
+
*/
|
|
14090
|
+
async function persistGeneratedFileAsFabFile(context, file) {
|
|
14091
|
+
const { sessionId, userId, db, storage, logger } = context;
|
|
14092
|
+
if (!sessionId) return;
|
|
14093
|
+
if (!db.fabfiles || !db.users || !db.adminSettings) {
|
|
14094
|
+
logger.warn("[persistGeneratedFileAsFabFile] missing db adapters — skipping FabFile persist");
|
|
14095
|
+
return;
|
|
14096
|
+
}
|
|
14097
|
+
try {
|
|
14098
|
+
await createFabFile(userId, {
|
|
14099
|
+
fileName: file.fileName,
|
|
14100
|
+
mimeType: file.mimeType,
|
|
14101
|
+
fileSize: file.content.length,
|
|
14102
|
+
type: KnowledgeType.FILE,
|
|
14103
|
+
content: file.content,
|
|
14104
|
+
contentType: file.mimeType,
|
|
14105
|
+
sessionId,
|
|
14106
|
+
prefix: "generated",
|
|
14107
|
+
tags: [{
|
|
14108
|
+
name: "generated",
|
|
14109
|
+
strength: 1
|
|
14110
|
+
}]
|
|
14111
|
+
}, {
|
|
14112
|
+
db: {
|
|
14113
|
+
fabFiles: db.fabfiles,
|
|
14114
|
+
adminSettings: db.adminSettings,
|
|
14115
|
+
users: db.users
|
|
14116
|
+
},
|
|
14117
|
+
storage: {
|
|
14118
|
+
upload: (path, content, options) => storage.upload(content, path, options),
|
|
14119
|
+
generateSignedUrl: (path, expireInSeconds, type) => storage.getSignedUrl(path, type ?? "get", { expiresIn: expireInSeconds })
|
|
14120
|
+
}
|
|
14121
|
+
});
|
|
14122
|
+
} catch (err) {
|
|
14123
|
+
logger.error("[persistGeneratedFileAsFabFile] failed to persist generated file (non-fatal)", err);
|
|
14124
|
+
}
|
|
14125
|
+
}
|
|
11795
14126
|
async function downloadImage$1(url) {
|
|
11796
14127
|
if (url.startsWith("data:image/")) {
|
|
11797
14128
|
const base64Data = url.split(",")[1];
|
|
@@ -11825,8 +14156,15 @@ async function processAndStoreImages(images, context) {
|
|
|
11825
14156
|
return Promise.all(images.map(async (image) => {
|
|
11826
14157
|
const buffer = await downloadImage$1(image);
|
|
11827
14158
|
const fileType = await fileTypeFromBuffer(buffer);
|
|
11828
|
-
const
|
|
11829
|
-
|
|
14159
|
+
const ext = fileType?.ext ?? "png";
|
|
14160
|
+
const filename = `${v4()}.${ext}`;
|
|
14161
|
+
const path = await context.imageGenerateStorage.upload(buffer, filename, {});
|
|
14162
|
+
await persistGeneratedFileAsFabFile(context, {
|
|
14163
|
+
fileName: `generated-image-${filename.slice(0, 8)}.${ext}`,
|
|
14164
|
+
mimeType: fileType?.mime ?? "image/png",
|
|
14165
|
+
content: buffer
|
|
14166
|
+
});
|
|
14167
|
+
return path;
|
|
11830
14168
|
}));
|
|
11831
14169
|
}
|
|
11832
14170
|
async function updateQuestAndReturnMarkdown$1(storedImageUrls, context) {
|
|
@@ -15476,37 +17814,92 @@ The problem must define jobs (each with ordered operations) and machines. Each o
|
|
|
15476
17814
|
}
|
|
15477
17815
|
})
|
|
15478
17816
|
};
|
|
17817
|
+
const FAMILY_IDS = [
|
|
17818
|
+
"routing",
|
|
17819
|
+
"packing",
|
|
17820
|
+
"assignment",
|
|
17821
|
+
"network",
|
|
17822
|
+
"partitioning",
|
|
17823
|
+
"selection",
|
|
17824
|
+
"economic",
|
|
17825
|
+
"continuous"
|
|
17826
|
+
];
|
|
17827
|
+
/** Run the model and pull a JSON object out of the response (handles code fences). */
|
|
17828
|
+
async function completeToJson(context, systemPrompt, userDescription) {
|
|
17829
|
+
let rawContent = "";
|
|
17830
|
+
await context.llm.complete(context.model ?? "gpt-4", [{
|
|
17831
|
+
role: "system",
|
|
17832
|
+
content: systemPrompt
|
|
17833
|
+
}, {
|
|
17834
|
+
role: "user",
|
|
17835
|
+
content: userDescription
|
|
17836
|
+
}], {
|
|
17837
|
+
temperature: .2,
|
|
17838
|
+
stream: false
|
|
17839
|
+
}, async (texts) => {
|
|
17840
|
+
rawContent = texts.filter((t) => t !== null && t !== void 0).join("");
|
|
17841
|
+
});
|
|
17842
|
+
let jsonStr = rawContent.trim();
|
|
17843
|
+
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
17844
|
+
if (codeBlockMatch) jsonStr = codeBlockMatch[1].trim();
|
|
17845
|
+
try {
|
|
17846
|
+
return { json: JSON.parse(jsonStr) };
|
|
17847
|
+
} catch {
|
|
17848
|
+
return { error: `Could not parse the model response as JSON. Raw response:\n${rawContent}` };
|
|
17849
|
+
}
|
|
17850
|
+
}
|
|
17851
|
+
/** Build the per-family system prompt from a real sample as the shape template. */
|
|
17852
|
+
function familyFormulationPrompt(familyId) {
|
|
17853
|
+
return `You convert a natural-language description into a "${familyId}" optimization problem as JSON.
|
|
17854
|
+
|
|
17855
|
+
Output ONLY a single JSON object matching this exact shape (a real ${familyId} example):
|
|
17856
|
+
|
|
17857
|
+
${JSON.stringify(FAMILY_SAMPLE_PROBLEMS[familyId][0], null, 2)}
|
|
17858
|
+
|
|
17859
|
+
Rules:
|
|
17860
|
+
- "family" MUST be exactly "${familyId}".
|
|
17861
|
+
- Keep it small and browser-solvable, at a scale similar to the example.
|
|
17862
|
+
- ids are integers starting at 0; names are short human-readable strings.
|
|
17863
|
+
- Output ONLY the JSON object — no prose, no markdown fences.`;
|
|
17864
|
+
}
|
|
15479
17865
|
const quantumFormulateTool = {
|
|
15480
17866
|
name: "quantum_formulate",
|
|
15481
17867
|
implementation: (context) => ({
|
|
15482
17868
|
toolFn: async (value) => {
|
|
15483
|
-
const
|
|
15484
|
-
|
|
17869
|
+
const params = value;
|
|
17870
|
+
const userDescription = params.description?.trim();
|
|
17871
|
+
if (!userDescription) return "Error: Please provide a description of the optimization problem to formulate.";
|
|
17872
|
+
if (params.familyId && !FAMILY_IDS.includes(params.familyId)) return `Error: unknown familyId "${String(params.familyId)}". Valid families: ${FAMILY_IDS.join(", ")}. Omit familyId to formulate a job-shop scheduling problem.`;
|
|
17873
|
+
const familyId = params.familyId || void 0;
|
|
15485
17874
|
try {
|
|
15486
|
-
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
17875
|
+
if (familyId) {
|
|
17876
|
+
const result = await completeToJson(context, familyFormulationPrompt(familyId), userDescription);
|
|
17877
|
+
if ("error" in result) return `Error: ${result.error}\n\nPlease rephrase with more specifics for a ${familyId} problem.`;
|
|
17878
|
+
const validated = FAMILY_PROBLEM_SCHEMAS[familyId].safeParse(result.json);
|
|
17879
|
+
if (!validated.success) return `Error: the model produced an invalid ${familyId} problem.\n${validated.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n")}\n\nPlease rephrase your description.`;
|
|
17880
|
+
const problem = validated.data;
|
|
17881
|
+
const summary = [
|
|
17882
|
+
`## Formulated: "${problem.name}"`,
|
|
17883
|
+
problem.description ? `\n${problem.description}` : "",
|
|
17884
|
+
"",
|
|
17885
|
+
`**${familyId} problem** — ready to load.`,
|
|
17886
|
+
"",
|
|
17887
|
+
`Open the ${familyId} console's Problem tab and click "Load problem" on the pending banner to review, tweak, and race solvers.`
|
|
17888
|
+
].filter((l) => l !== void 0).join("\n");
|
|
17889
|
+
return JSON.stringify({
|
|
17890
|
+
__uiSideEffect: true,
|
|
17891
|
+
type: "populateFamilyProblem",
|
|
17892
|
+
payload: {
|
|
17893
|
+
familyId,
|
|
17894
|
+
problem
|
|
17895
|
+
},
|
|
17896
|
+
displayMessage: summary
|
|
17897
|
+
});
|
|
15507
17898
|
}
|
|
15508
|
-
const
|
|
15509
|
-
if (
|
|
17899
|
+
const result = await completeToJson(context, PROBLEM_FORMULATION_PROMPT, userDescription);
|
|
17900
|
+
if ("error" in result) return `Error: ${result.error}\n\nPlease try rephrasing with specific jobs, machines, and processing times.`;
|
|
17901
|
+
const validated = SchedulingProblemSchema.safeParse(result.json);
|
|
17902
|
+
if (!validated.success) return `Error: LLM generated an invalid problem structure.\n${validated.error.issues.map((i) => ` - ${i.path.join(".")}: ${i.message}`).join("\n")}\n\nPlease try rephrasing your description.`;
|
|
15510
17903
|
const problem = validated.data;
|
|
15511
17904
|
const totalOps = problem.jobs.reduce((s, j) => s + j.operations.length, 0);
|
|
15512
17905
|
const humanReadableSummary = [
|
|
@@ -15541,21 +17934,28 @@ const quantumFormulateTool = {
|
|
|
15541
17934
|
},
|
|
15542
17935
|
toolSchema: {
|
|
15543
17936
|
name: "quantum_formulate",
|
|
15544
|
-
description: `Convert a natural
|
|
17937
|
+
description: `Convert a natural-language description of an optimization problem into a structured problem that the /opti solvers can run.
|
|
15545
17938
|
|
|
15546
|
-
|
|
17939
|
+
Pass \`familyId\` to target one of the eight pattern families; omit it for job-shop scheduling:
|
|
17940
|
+
- routing (TSP / vehicle routing), packing (bin packing), assignment (who does what),
|
|
17941
|
+
network (max-cut), partitioning (balanced k-way), selection (knapsack / portfolio),
|
|
17942
|
+
economic (combinatorial auction), continuous (function minimization).
|
|
15547
17943
|
|
|
15548
|
-
|
|
15549
|
-
|
|
15550
|
-
- "Schedule 4 software builds across 2 CI runners. Build A needs compile (5min) then test (3min)..."
|
|
15551
|
-
- "A bakery needs to make 5 cakes. Each cake goes through mixing, baking, and decorating on separate stations."`,
|
|
15552
|
-
strict: true,
|
|
17944
|
+
Describe the scenario in plain English — the entities, resources, costs/values, and constraints — and the tool produces a structured problem definition for that family.`,
|
|
17945
|
+
strict: false,
|
|
15553
17946
|
parameters: {
|
|
15554
17947
|
type: "object",
|
|
15555
|
-
properties: {
|
|
15556
|
-
|
|
15557
|
-
|
|
15558
|
-
|
|
17948
|
+
properties: {
|
|
17949
|
+
description: {
|
|
17950
|
+
type: "string",
|
|
17951
|
+
description: "Natural-language description of the optimization problem to formulate"
|
|
17952
|
+
},
|
|
17953
|
+
familyId: {
|
|
17954
|
+
type: "string",
|
|
17955
|
+
enum: FAMILY_IDS,
|
|
17956
|
+
description: "Optional optimization family. Omit for job-shop scheduling; otherwise one of the eight families."
|
|
17957
|
+
}
|
|
17958
|
+
},
|
|
15559
17959
|
required: ["description"],
|
|
15560
17960
|
additionalProperties: false
|
|
15561
17961
|
}
|
|
@@ -15869,6 +18269,7 @@ Please generate a complete, well-structured notebook that performs this analysis
|
|
|
15869
18269
|
}
|
|
15870
18270
|
})
|
|
15871
18271
|
};
|
|
18272
|
+
const XLSX_MIME = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
15872
18273
|
const LIMITS = {
|
|
15873
18274
|
MAX_SHEETS: 10,
|
|
15874
18275
|
MAX_CELLS_PER_SHEET: 1e4,
|
|
@@ -16187,9 +18588,14 @@ const excelGenerationTool = {
|
|
|
16187
18588
|
const sanitizedName = sanitizeFilename(params.filename);
|
|
16188
18589
|
const filename = `${sanitizedName}-${v4().slice(0, 8)}.xlsx`;
|
|
16189
18590
|
await context.imageGenerateStorage.upload(buffer, filename, {
|
|
16190
|
-
ContentType:
|
|
18591
|
+
ContentType: XLSX_MIME,
|
|
16191
18592
|
ContentDisposition: `attachment; filename="${sanitizedName}.xlsx"`
|
|
16192
18593
|
});
|
|
18594
|
+
await persistGeneratedFileAsFabFile(context, {
|
|
18595
|
+
fileName: `${sanitizedName}.xlsx`,
|
|
18596
|
+
mimeType: XLSX_MIME,
|
|
18597
|
+
content: buffer
|
|
18598
|
+
});
|
|
16193
18599
|
await context.onFinish?.("excel_generation", [filename]);
|
|
16194
18600
|
await context.statusUpdate({ images: [filename] });
|
|
16195
18601
|
return `Successfully generated Excel file: ${sanitizedName}.xlsx`;
|
|
@@ -17475,10 +19881,11 @@ const b4mTools = {
|
|
|
17475
19881
|
fmp_financial_data: fmpTool,
|
|
17476
19882
|
skill: skillTool
|
|
17477
19883
|
};
|
|
17478
|
-
const generateTools = (userId, user, logger, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model, imageProcessorLambdaName, tools = b4mTools, allowedDirectories, entitlementKeys = []) => {
|
|
19884
|
+
const generateTools = (userId, user, logger, { db }, storage, imageGenerateStorage, statusUpdate, onStart, onFinish, llm, config, model, imageProcessorLambdaName, tools = b4mTools, allowedDirectories, entitlementKeys = [], sessionId) => {
|
|
17479
19885
|
const context = {
|
|
17480
19886
|
userId,
|
|
17481
19887
|
user,
|
|
19888
|
+
sessionId,
|
|
17482
19889
|
logger,
|
|
17483
19890
|
db,
|
|
17484
19891
|
storage,
|
|
@@ -18499,7 +20906,11 @@ var ReActAgent = class extends EventEmitter {
|
|
|
18499
20906
|
* This can be overridden in the context or customized here
|
|
18500
20907
|
*/
|
|
18501
20908
|
getSystemPrompt() {
|
|
18502
|
-
|
|
20909
|
+
const base = this.context.systemPrompt ? this.context.systemPrompt : this.buildDefaultSystemPrompt();
|
|
20910
|
+
const persona = this.context.personaPrompt?.trim();
|
|
20911
|
+
return persona ? `${persona}\n\n${base}` : base;
|
|
20912
|
+
}
|
|
20913
|
+
buildDefaultSystemPrompt() {
|
|
18503
20914
|
return `You are an autonomous AI agent with access to tools. Your job is to solve problems by taking action, not by asking for clarification.
|
|
18504
20915
|
|
|
18505
20916
|
CORE PRINCIPLES:
|
|
@@ -19122,7 +21533,7 @@ Remember: You are an autonomous AGENT. Act independently and solve problems proa
|
|
|
19122
21533
|
})}</function>`;
|
|
19123
21534
|
}
|
|
19124
21535
|
}
|
|
19125
|
-
return `Error: Tool ${toolUse.name} not
|
|
21536
|
+
return `Error: Tool "${toolUse.name}" is not available in this context and cannot be called. Do NOT attempt to call it again. Proceed without it — call other available tools if your plan still needs them, or compose your final answer from the information already gathered if no more tools are needed.`;
|
|
19126
21537
|
}
|
|
19127
21538
|
try {
|
|
19128
21539
|
const params = this.parseToolArguments(toolUse.arguments);
|
|
@@ -20490,33 +22901,6 @@ z.object({
|
|
|
20490
22901
|
fabFileId: z.string(),
|
|
20491
22902
|
chunkId: z.string()
|
|
20492
22903
|
});
|
|
20493
|
-
z.object({
|
|
20494
|
-
fileName: z.string(),
|
|
20495
|
-
mimeType: z.string(),
|
|
20496
|
-
fileSize: z.number(),
|
|
20497
|
-
type: z.enum(KnowledgeType),
|
|
20498
|
-
content: z.union([z.string(), z.instanceof(Buffer)]).optional(),
|
|
20499
|
-
organizationId: z.string().optional(),
|
|
20500
|
-
/**
|
|
20501
|
-
* Content type of the file
|
|
20502
|
-
* @example 'text/markdown'
|
|
20503
|
-
* @example 'application/pdf'
|
|
20504
|
-
* @example 'application/octet-stream' for binary files
|
|
20505
|
-
*/
|
|
20506
|
-
contentType: z.string().optional(),
|
|
20507
|
-
public: z.boolean().optional(),
|
|
20508
|
-
prefix: z.string().optional(),
|
|
20509
|
-
system: z.boolean().optional(),
|
|
20510
|
-
tags: z.array(z.object({
|
|
20511
|
-
name: z.string(),
|
|
20512
|
-
strength: z.number()
|
|
20513
|
-
})).optional(),
|
|
20514
|
-
systemPriority: z.number().optional(),
|
|
20515
|
-
sessionId: z.string().optional(),
|
|
20516
|
-
contentHash: z.string().optional(),
|
|
20517
|
-
batchId: z.string().optional(),
|
|
20518
|
-
relativePath: z.string().optional()
|
|
20519
|
-
});
|
|
20520
22904
|
z.object({ sessionId: z.string() });
|
|
20521
22905
|
z.object({ questId: z.string() });
|
|
20522
22906
|
z.object({ url: z.string().regex(/^(?!https?:\/\/(drive|docs)\.google\.com\/(?:file\/d\/|open\?id=|uc\?id=|document\/d\/|spreadsheets\/d\/|presentation\/d\/|forms\/d\/|drive\/folders\/)([a-zA-Z0-9_-]{10,})).+/) });
|