@bike4mind/cli 0.2.31-b4m-cli-undo-command.19534 → 0.2.31-b4m-cli-undo-command.19598
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/{artifactExtractor-T6NJ7V7P.js → artifactExtractor-IKIJZW6C.js} +1 -1
- package/dist/{chunk-F4PXVLZX.js → chunk-4P27WV34.js} +2 -2
- package/dist/{chunk-WVFOWKNW.js → chunk-BXNVLTPU.js} +6 -6
- package/dist/{chunk-JWJF6O4L.js → chunk-DQHCE3TN.js} +2 -2
- package/dist/{chunk-NI22LIK3.js → chunk-PLA2VBQW.js} +13 -1
- package/dist/{chunk-3SPW5FYJ.js → chunk-PV6PZFPC.js} +67 -5
- package/dist/{chunk-ERV5G6MX.js → chunk-S6AUIWWB.js} +2 -2
- package/dist/commands/doctorCommand.js +1 -1
- package/dist/commands/updateCommand.js +1 -1
- package/dist/{create-XOEMSBER.js → create-PVJSCD5H.js} +3 -3
- package/dist/index.js +991 -36
- package/dist/{llmMarkdownGenerator-NPX7ULSW.js → llmMarkdownGenerator-BMYWIXYB.js} +1 -1
- package/dist/{markdownGenerator-TVJ2RQXC.js → markdownGenerator-H7BNB5KO.js} +1 -1
- package/dist/{mementoService-HGH2XVLM.js → mementoService-RDPCVXWF.js} +3 -3
- package/dist/{src-JZ6OHGTX.js → src-DCF72PTU.js} +2 -2
- package/dist/{src-2BRBILH7.js → src-IKK3N7TZ.js} +1 -1
- package/dist/{subtractCredits-4VIHTUR4.js → subtractCredits-K4PWRUF4.js} +3 -3
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "./chunk-GQGOWACU.js";
|
|
3
|
-
import "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
import "./chunk-4P27WV34.js";
|
|
4
|
+
import "./chunk-S6AUIWWB.js";
|
|
5
5
|
import "./chunk-BPFEGDC7.js";
|
|
6
6
|
import "./chunk-BDQBOLYG.js";
|
|
7
7
|
import {
|
|
8
8
|
getEffectiveApiKey,
|
|
9
9
|
getOpenWeatherKey,
|
|
10
10
|
getSerperKey
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DQHCE3TN.js";
|
|
12
12
|
import {
|
|
13
13
|
ConfigStore,
|
|
14
14
|
logger
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import {
|
|
17
17
|
checkForUpdate,
|
|
18
18
|
package_default
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-BXNVLTPU.js";
|
|
20
20
|
import {
|
|
21
21
|
selectActiveBackgroundAgents,
|
|
22
22
|
useCliStore
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
OpenAIBackend,
|
|
33
33
|
OpenAIImageService,
|
|
34
34
|
XAIImageService
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-PV6PZFPC.js";
|
|
36
36
|
import {
|
|
37
37
|
AiEvents,
|
|
38
38
|
ApiKeyEvents,
|
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
getMcpProviderMetadata,
|
|
91
91
|
getViewById,
|
|
92
92
|
resolveNavigationIntents
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-PLA2VBQW.js";
|
|
94
94
|
import {
|
|
95
95
|
Logger
|
|
96
96
|
} from "./chunk-PFBYGCOW.js";
|
|
@@ -1368,11 +1368,11 @@ var JobItem = React8.memo(function JobItem2({
|
|
|
1368
1368
|
job,
|
|
1369
1369
|
indented = false
|
|
1370
1370
|
}) {
|
|
1371
|
-
const
|
|
1371
|
+
const elapsed2 = Math.round((Date.now() - job.startTime) / 1e3);
|
|
1372
1372
|
const maxTaskLength = indented ? 50 : 60;
|
|
1373
1373
|
const taskPreview = job.task.length > maxTaskLength ? job.task.slice(0, maxTaskLength - 3) + "..." : job.task;
|
|
1374
1374
|
const isQueued = job.status === "queued";
|
|
1375
|
-
return /* @__PURE__ */ React8.createElement(Box7, null, indented && /* @__PURE__ */ React8.createElement(Text7, null, " "), isQueued ? /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u23F3") : /* @__PURE__ */ React8.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text7, { color: isQueued ? "yellow" : "blue" }, " ", job.agentName), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, " ", "[", job.id, "] ", taskPreview, " ", isQueued ? "(queued)" : `(${
|
|
1375
|
+
return /* @__PURE__ */ React8.createElement(Box7, null, indented && /* @__PURE__ */ React8.createElement(Text7, null, " "), isQueued ? /* @__PURE__ */ React8.createElement(Text7, { color: "yellow" }, "\u23F3") : /* @__PURE__ */ React8.createElement(Text7, { color: "blue" }, /* @__PURE__ */ React8.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React8.createElement(Text7, { color: isQueued ? "yellow" : "blue" }, " ", job.agentName), /* @__PURE__ */ React8.createElement(Text7, { dimColor: true }, " ", "[", job.id, "] ", taskPreview, " ", isQueued ? "(queued)" : `(${elapsed2}s)`));
|
|
1376
1376
|
});
|
|
1377
1377
|
function formatStatusCounts(jobs) {
|
|
1378
1378
|
let running = 0;
|
|
@@ -2912,13 +2912,16 @@ var CheckpointStore = class {
|
|
|
2912
2912
|
try {
|
|
2913
2913
|
let hasChanges = false;
|
|
2914
2914
|
for (const filePath of filePaths) {
|
|
2915
|
-
const absolutePath =
|
|
2915
|
+
const absolutePath = this.validatePathWithinProject(filePath);
|
|
2916
2916
|
const shadowPath = path6.join(this.shadowRepoDir, filePath);
|
|
2917
2917
|
const shadowDir = path6.dirname(shadowPath);
|
|
2918
2918
|
const absentMarkerPath = path6.join(shadowDir, `${path6.basename(filePath)}${ABSENT_MARKER}`);
|
|
2919
2919
|
await fs5.mkdir(shadowDir, { recursive: true });
|
|
2920
2920
|
if (existsSync4(absolutePath)) {
|
|
2921
|
-
const stats = await fs5.
|
|
2921
|
+
const stats = await fs5.lstat(absolutePath);
|
|
2922
|
+
if (stats.isSymbolicLink()) {
|
|
2923
|
+
continue;
|
|
2924
|
+
}
|
|
2922
2925
|
if (stats.size > MAX_FILE_SIZE2) {
|
|
2923
2926
|
continue;
|
|
2924
2927
|
}
|
|
@@ -2995,7 +2998,7 @@ var CheckpointStore = class {
|
|
|
2995
2998
|
throw new Error(`Checkpoint #${index} not found. Use /checkpoints to see available restore points.`);
|
|
2996
2999
|
}
|
|
2997
3000
|
for (const filePath of checkpoint.filePaths) {
|
|
2998
|
-
const absolutePath =
|
|
3001
|
+
const absolutePath = this.validatePathWithinProject(filePath);
|
|
2999
3002
|
try {
|
|
3000
3003
|
const content = this.git("show", `${checkpoint.id}:${filePath}`);
|
|
3001
3004
|
await fs5.mkdir(path6.dirname(absolutePath), { recursive: true });
|
|
@@ -3031,7 +3034,9 @@ var CheckpointStore = class {
|
|
|
3031
3034
|
}
|
|
3032
3035
|
const diffParts = [];
|
|
3033
3036
|
for (const filePath of checkpoint.filePaths) {
|
|
3034
|
-
const absolutePath =
|
|
3037
|
+
const absolutePath = this.validatePathWithinProject(filePath);
|
|
3038
|
+
const tmpCheckpoint = path6.join(this.shadowRepoDir, ".diff-a");
|
|
3039
|
+
const tmpCurrent = path6.join(this.shadowRepoDir, ".diff-b");
|
|
3035
3040
|
try {
|
|
3036
3041
|
let checkpointContent;
|
|
3037
3042
|
try {
|
|
@@ -3046,8 +3051,6 @@ var CheckpointStore = class {
|
|
|
3046
3051
|
if (checkpointContent === currentContent) {
|
|
3047
3052
|
continue;
|
|
3048
3053
|
}
|
|
3049
|
-
const tmpCheckpoint = path6.join(this.shadowRepoDir, ".diff-a");
|
|
3050
|
-
const tmpCurrent = path6.join(this.shadowRepoDir, ".diff-b");
|
|
3051
3054
|
writeFileSync(tmpCheckpoint, checkpointContent, "utf-8");
|
|
3052
3055
|
writeFileSync(tmpCurrent, currentContent, "utf-8");
|
|
3053
3056
|
try {
|
|
@@ -3070,12 +3073,16 @@ ${output}`);
|
|
|
3070
3073
|
}
|
|
3071
3074
|
}
|
|
3072
3075
|
}
|
|
3076
|
+
} catch {
|
|
3077
|
+
} finally {
|
|
3073
3078
|
try {
|
|
3074
3079
|
unlinkSync(tmpCheckpoint);
|
|
3080
|
+
} catch {
|
|
3081
|
+
}
|
|
3082
|
+
try {
|
|
3075
3083
|
unlinkSync(tmpCurrent);
|
|
3076
3084
|
} catch {
|
|
3077
3085
|
}
|
|
3078
|
-
} catch {
|
|
3079
3086
|
}
|
|
3080
3087
|
}
|
|
3081
3088
|
return diffParts.join("\n");
|
|
@@ -3109,6 +3116,18 @@ ${output}`);
|
|
|
3109
3116
|
}
|
|
3110
3117
|
}
|
|
3111
3118
|
// --- Private helpers ---
|
|
3119
|
+
/**
|
|
3120
|
+
* Validate that a file path resolves within the project directory.
|
|
3121
|
+
* Prevents path traversal attacks (e.g., ../../etc/passwd).
|
|
3122
|
+
*/
|
|
3123
|
+
validatePathWithinProject(filePath) {
|
|
3124
|
+
const absolutePath = path6.resolve(this.projectDir, filePath);
|
|
3125
|
+
const normalizedProject = path6.resolve(this.projectDir) + path6.sep;
|
|
3126
|
+
if (!absolutePath.startsWith(normalizedProject) && absolutePath !== path6.resolve(this.projectDir)) {
|
|
3127
|
+
throw new Error(`Path traversal detected: ${filePath}`);
|
|
3128
|
+
}
|
|
3129
|
+
return absolutePath;
|
|
3130
|
+
}
|
|
3112
3131
|
/**
|
|
3113
3132
|
* Execute a git command in the shadow repo
|
|
3114
3133
|
*/
|
|
@@ -10531,7 +10550,8 @@ var SchedulingProblemSchema = z139.object({
|
|
|
10531
10550
|
name: z139.string(),
|
|
10532
10551
|
description: z139.string().optional(),
|
|
10533
10552
|
jobs: z139.array(JobSchema),
|
|
10534
|
-
machines: z139.array(MachineSchema)
|
|
10553
|
+
machines: z139.array(MachineSchema),
|
|
10554
|
+
solvedJobUrl: z139.string().url().optional()
|
|
10535
10555
|
});
|
|
10536
10556
|
var SolverIdSchema = z139.enum([
|
|
10537
10557
|
"greedy",
|
|
@@ -11196,6 +11216,351 @@ function constructSolution(allOps, pheromone, heuristic, rng) {
|
|
|
11196
11216
|
return result;
|
|
11197
11217
|
}
|
|
11198
11218
|
|
|
11219
|
+
// ../../b4m-core/packages/quantum/dist/src/solvers/highs-formulation.js
|
|
11220
|
+
function analyzeProblemComplexity(problem) {
|
|
11221
|
+
const numJobs = problem.jobs.length;
|
|
11222
|
+
const numMachines = problem.machines.length;
|
|
11223
|
+
const opsPerJob = problem.jobs[0]?.operations.length || 0;
|
|
11224
|
+
const totalOps = problem.jobs.reduce((sum2, j) => sum2 + j.operations.length, 0);
|
|
11225
|
+
const machineOpCounts = /* @__PURE__ */ new Map();
|
|
11226
|
+
for (const job of problem.jobs) {
|
|
11227
|
+
for (const op of job.operations) {
|
|
11228
|
+
machineOpCounts.set(op.machineId, (machineOpCounts.get(op.machineId) || 0) + 1);
|
|
11229
|
+
}
|
|
11230
|
+
}
|
|
11231
|
+
const opCounts = Array.from(machineOpCounts.values());
|
|
11232
|
+
const minOps = opCounts.length > 0 ? Math.min(...opCounts) : 0;
|
|
11233
|
+
const maxOps = opCounts.length > 0 ? Math.max(...opCounts) : 0;
|
|
11234
|
+
const avgOps = opCounts.length > 0 ? opCounts.reduce((a, b) => a + b, 0) / opCounts.length : 0;
|
|
11235
|
+
let binaryVars = 0;
|
|
11236
|
+
for (const n of opCounts) {
|
|
11237
|
+
binaryVars += n * (n - 1) / 2;
|
|
11238
|
+
}
|
|
11239
|
+
const startTimeVars = totalOps;
|
|
11240
|
+
const totalVars = startTimeVars + binaryVars + 1;
|
|
11241
|
+
const jobPrecedenceConstraints = problem.jobs.reduce((sum2, j) => sum2 + Math.max(0, j.operations.length - 1), 0);
|
|
11242
|
+
const machineDisjunctionConstraints = 2 * binaryVars;
|
|
11243
|
+
const makespanConstraints = totalOps;
|
|
11244
|
+
const totalConstraints = jobPrecedenceConstraints + machineDisjunctionConstraints + makespanConstraints;
|
|
11245
|
+
return {
|
|
11246
|
+
numJobs,
|
|
11247
|
+
numMachines,
|
|
11248
|
+
opsPerJob,
|
|
11249
|
+
totalOps,
|
|
11250
|
+
startTimeVars,
|
|
11251
|
+
binaryVars,
|
|
11252
|
+
totalVars,
|
|
11253
|
+
jobPrecedenceConstraints,
|
|
11254
|
+
machineDisjunctionConstraints,
|
|
11255
|
+
makespanConstraints,
|
|
11256
|
+
totalConstraints,
|
|
11257
|
+
opsPerMachine: { min: minOps, max: maxOps, avg: Math.round(avgOps * 10) / 10 }
|
|
11258
|
+
};
|
|
11259
|
+
}
|
|
11260
|
+
function estimateViability(c) {
|
|
11261
|
+
if (c.opsPerMachine.max > 10) {
|
|
11262
|
+
return {
|
|
11263
|
+
viable: false,
|
|
11264
|
+
risk: "high",
|
|
11265
|
+
recommendation: `Too many ops on one machine (${c.opsPerMachine.max}). Add more machines to spread the load, or use Simulated Annealing.`
|
|
11266
|
+
};
|
|
11267
|
+
}
|
|
11268
|
+
if (c.binaryVars <= 80 && c.totalOps <= 40 && c.opsPerMachine.max <= 6) {
|
|
11269
|
+
return {
|
|
11270
|
+
viable: true,
|
|
11271
|
+
risk: "low",
|
|
11272
|
+
recommendation: "Should solve quickly (< 1 second)"
|
|
11273
|
+
};
|
|
11274
|
+
}
|
|
11275
|
+
if (c.binaryVars <= 150 && c.totalOps <= 80 && c.opsPerMachine.max <= 8) {
|
|
11276
|
+
return {
|
|
11277
|
+
viable: true,
|
|
11278
|
+
risk: "medium",
|
|
11279
|
+
recommendation: "Should solve in 1-30 seconds. WASM may have occasional instability."
|
|
11280
|
+
};
|
|
11281
|
+
}
|
|
11282
|
+
if (c.binaryVars > 150) {
|
|
11283
|
+
return {
|
|
11284
|
+
viable: false,
|
|
11285
|
+
risk: "high",
|
|
11286
|
+
recommendation: `Too many binary vars (${c.binaryVars} > 150). Use Simulated Annealing or Tabu Search for this size.`
|
|
11287
|
+
};
|
|
11288
|
+
}
|
|
11289
|
+
if (c.totalOps > 80) {
|
|
11290
|
+
return {
|
|
11291
|
+
viable: false,
|
|
11292
|
+
risk: "high",
|
|
11293
|
+
recommendation: `Too many operations (${c.totalOps} > 80). Use Simulated Annealing or Tabu Search for this size.`
|
|
11294
|
+
};
|
|
11295
|
+
}
|
|
11296
|
+
return {
|
|
11297
|
+
viable: false,
|
|
11298
|
+
risk: "high",
|
|
11299
|
+
recommendation: "Exceeds tested parameters. Consider using Simulated Annealing or Tabu Search."
|
|
11300
|
+
};
|
|
11301
|
+
}
|
|
11302
|
+
function generateLPFormulation(problem) {
|
|
11303
|
+
const ops = [];
|
|
11304
|
+
for (const job of problem.jobs) {
|
|
11305
|
+
for (let opIdx = 0; opIdx < job.operations.length; opIdx++) {
|
|
11306
|
+
const op = job.operations[opIdx];
|
|
11307
|
+
const varName = `sJ${job.id}O${opIdx + 1}`;
|
|
11308
|
+
ops.push({
|
|
11309
|
+
jobId: job.id,
|
|
11310
|
+
machineId: op.machineId,
|
|
11311
|
+
opIndex: opIdx,
|
|
11312
|
+
duration: op.duration,
|
|
11313
|
+
varName
|
|
11314
|
+
});
|
|
11315
|
+
}
|
|
11316
|
+
}
|
|
11317
|
+
const bigM = ops.reduce((sum2, op) => sum2 + op.duration, 0);
|
|
11318
|
+
const machineOps = /* @__PURE__ */ new Map();
|
|
11319
|
+
for (const op of ops) {
|
|
11320
|
+
const machOps = machineOps.get(op.machineId) || [];
|
|
11321
|
+
machOps.push(op);
|
|
11322
|
+
machineOps.set(op.machineId, machOps);
|
|
11323
|
+
}
|
|
11324
|
+
const lines = [];
|
|
11325
|
+
lines.push("Minimize obj: Cmax");
|
|
11326
|
+
lines.push("");
|
|
11327
|
+
lines.push("Subject To");
|
|
11328
|
+
for (const job of problem.jobs) {
|
|
11329
|
+
for (let i = 0; i < job.operations.length - 1; i++) {
|
|
11330
|
+
const op1VarName = `sJ${job.id}O${i + 1}`;
|
|
11331
|
+
const op2VarName = `sJ${job.id}O${i + 2}`;
|
|
11332
|
+
const duration = job.operations[i].duration;
|
|
11333
|
+
const constraintName = `job${op1VarName}to${op2VarName}`;
|
|
11334
|
+
lines.push(` ${constraintName}: ${op1VarName} - ${op2VarName} <= ${-duration}`);
|
|
11335
|
+
}
|
|
11336
|
+
}
|
|
11337
|
+
const binaryVars = [];
|
|
11338
|
+
for (const [, machOps] of machineOps) {
|
|
11339
|
+
if (machOps.length < 2)
|
|
11340
|
+
continue;
|
|
11341
|
+
for (let i = 0; i < machOps.length; i++) {
|
|
11342
|
+
for (let j = i + 1; j < machOps.length; j++) {
|
|
11343
|
+
const op1 = machOps[i];
|
|
11344
|
+
const op2 = machOps[j];
|
|
11345
|
+
const yVar = `y${op1.varName}x${op2.varName}`;
|
|
11346
|
+
binaryVars.push(yVar);
|
|
11347
|
+
const c1Name = `d${op1.varName}b${op2.varName}`;
|
|
11348
|
+
lines.push(` ${c1Name}: ${op1.varName} - ${op2.varName} + ${bigM} ${yVar} <= ${bigM - op1.duration}`);
|
|
11349
|
+
const c2Name = `d${op2.varName}b${op1.varName}`;
|
|
11350
|
+
lines.push(` ${c2Name}: ${op2.varName} - ${op1.varName} - ${bigM} ${yVar} <= ${-op2.duration}`);
|
|
11351
|
+
}
|
|
11352
|
+
}
|
|
11353
|
+
}
|
|
11354
|
+
for (const op of ops) {
|
|
11355
|
+
const constraintName = `mk${op.varName}`;
|
|
11356
|
+
lines.push(` ${constraintName}: ${op.varName} - Cmax <= ${-op.duration}`);
|
|
11357
|
+
}
|
|
11358
|
+
lines.push("");
|
|
11359
|
+
lines.push("Bounds");
|
|
11360
|
+
for (const op of ops) {
|
|
11361
|
+
lines.push(` ${op.varName} >= 0`);
|
|
11362
|
+
}
|
|
11363
|
+
lines.push(" Cmax >= 0");
|
|
11364
|
+
lines.push("");
|
|
11365
|
+
if (binaryVars.length > 0) {
|
|
11366
|
+
lines.push("Binary");
|
|
11367
|
+
for (const v of binaryVars) {
|
|
11368
|
+
lines.push(` ${v}`);
|
|
11369
|
+
}
|
|
11370
|
+
lines.push("");
|
|
11371
|
+
}
|
|
11372
|
+
lines.push("End");
|
|
11373
|
+
return lines.join("\n");
|
|
11374
|
+
}
|
|
11375
|
+
function parseSolution(problem, columns) {
|
|
11376
|
+
const schedule = [];
|
|
11377
|
+
const varToOp = /* @__PURE__ */ new Map();
|
|
11378
|
+
for (const job of problem.jobs) {
|
|
11379
|
+
for (let opIdx = 0; opIdx < job.operations.length; opIdx++) {
|
|
11380
|
+
const op = job.operations[opIdx];
|
|
11381
|
+
const varName = `sJ${job.id}O${opIdx + 1}`;
|
|
11382
|
+
varToOp.set(varName, {
|
|
11383
|
+
jobId: job.id,
|
|
11384
|
+
machineId: op.machineId,
|
|
11385
|
+
opIndex: opIdx,
|
|
11386
|
+
duration: op.duration
|
|
11387
|
+
});
|
|
11388
|
+
}
|
|
11389
|
+
}
|
|
11390
|
+
for (const [varName, col] of Object.entries(columns)) {
|
|
11391
|
+
if (varName.startsWith("sJ")) {
|
|
11392
|
+
const opInfo = varToOp.get(varName);
|
|
11393
|
+
if (opInfo) {
|
|
11394
|
+
const startTime = Math.round(col.Primal);
|
|
11395
|
+
schedule.push({
|
|
11396
|
+
jobId: opInfo.jobId,
|
|
11397
|
+
machineId: opInfo.machineId,
|
|
11398
|
+
operationIndex: opInfo.opIndex,
|
|
11399
|
+
startTime,
|
|
11400
|
+
endTime: startTime + opInfo.duration
|
|
11401
|
+
});
|
|
11402
|
+
}
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
schedule.sort((a, b) => a.startTime - b.startTime);
|
|
11406
|
+
return schedule;
|
|
11407
|
+
}
|
|
11408
|
+
function validateSchedule(problem, schedule) {
|
|
11409
|
+
const errors = [];
|
|
11410
|
+
const scheduledKeys = new Set(schedule.map((s) => `${s.jobId}-${s.operationIndex}`));
|
|
11411
|
+
for (const job of problem.jobs) {
|
|
11412
|
+
for (let opIdx = 0; opIdx < job.operations.length; opIdx++) {
|
|
11413
|
+
if (!scheduledKeys.has(`${job.id}-${opIdx}`)) {
|
|
11414
|
+
errors.push(`Operation (job=${job.id}, opIndex=${opIdx}) not scheduled`);
|
|
11415
|
+
}
|
|
11416
|
+
}
|
|
11417
|
+
}
|
|
11418
|
+
const byMachine = /* @__PURE__ */ new Map();
|
|
11419
|
+
for (const s of schedule) {
|
|
11420
|
+
const mOps = byMachine.get(s.machineId) || [];
|
|
11421
|
+
mOps.push(s);
|
|
11422
|
+
byMachine.set(s.machineId, mOps);
|
|
11423
|
+
}
|
|
11424
|
+
for (const [machineId, mOps] of byMachine) {
|
|
11425
|
+
mOps.sort((a, b) => a.startTime - b.startTime);
|
|
11426
|
+
for (let i = 0; i < mOps.length - 1; i++) {
|
|
11427
|
+
if (mOps[i].endTime > mOps[i + 1].startTime) {
|
|
11428
|
+
errors.push(`Machine ${machineId}: (job=${mOps[i].jobId},op=${mOps[i].operationIndex}) ends ${mOps[i].endTime} overlaps (job=${mOps[i + 1].jobId},op=${mOps[i + 1].operationIndex}) starts ${mOps[i + 1].startTime}`);
|
|
11429
|
+
}
|
|
11430
|
+
}
|
|
11431
|
+
}
|
|
11432
|
+
const opEndTime = /* @__PURE__ */ new Map();
|
|
11433
|
+
for (const s of schedule) {
|
|
11434
|
+
opEndTime.set(`${s.jobId}-${s.operationIndex}`, s.endTime);
|
|
11435
|
+
}
|
|
11436
|
+
for (const job of problem.jobs) {
|
|
11437
|
+
for (let i = 0; i < job.operations.length - 1; i++) {
|
|
11438
|
+
const op1End = opEndTime.get(`${job.id}-${i}`) || 0;
|
|
11439
|
+
const op2 = schedule.find((s) => s.jobId === job.id && s.operationIndex === i + 1);
|
|
11440
|
+
if (op2 && op1End > op2.startTime) {
|
|
11441
|
+
errors.push(`Job ${job.id}: op ${i} ends at ${op1End} but op ${i + 1} starts at ${op2.startTime}`);
|
|
11442
|
+
}
|
|
11443
|
+
}
|
|
11444
|
+
}
|
|
11445
|
+
return { valid: errors.length === 0, errors };
|
|
11446
|
+
}
|
|
11447
|
+
|
|
11448
|
+
// ../../b4m-core/packages/quantum/dist/src/solvers/highs-solver.js
|
|
11449
|
+
var MAX_BINARY_VARS = 150;
|
|
11450
|
+
var MAX_TOTAL_OPS = 80;
|
|
11451
|
+
var MAX_OPS_PER_MACHINE = 8;
|
|
11452
|
+
async function loadHiGHS() {
|
|
11453
|
+
const highsLoader = (await import("highs")).default;
|
|
11454
|
+
const highs = await highsLoader({
|
|
11455
|
+
locateFile: (file) => {
|
|
11456
|
+
const globalSelf = globalThis;
|
|
11457
|
+
if (globalSelf.location?.origin) {
|
|
11458
|
+
return `${globalSelf.location.origin}/${file}`;
|
|
11459
|
+
}
|
|
11460
|
+
return file;
|
|
11461
|
+
}
|
|
11462
|
+
});
|
|
11463
|
+
return highs;
|
|
11464
|
+
}
|
|
11465
|
+
function elapsed(startTime) {
|
|
11466
|
+
return typeof performance !== "undefined" ? performance.now() - startTime : Date.now() - startTime;
|
|
11467
|
+
}
|
|
11468
|
+
var highsSolver = {
|
|
11469
|
+
id: "highs",
|
|
11470
|
+
name: "HiGHS (WASM)",
|
|
11471
|
+
description: "Open-source MIP solver providing provably optimal solutions for small-to-medium scheduling problems via WASM.",
|
|
11472
|
+
async solve(problem, options) {
|
|
11473
|
+
const startTime = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
11474
|
+
const reportProgress = (percentage, bestMakespan) => {
|
|
11475
|
+
options?.onProgress?.({
|
|
11476
|
+
solverId: "highs",
|
|
11477
|
+
percentage,
|
|
11478
|
+
bestMakespan
|
|
11479
|
+
});
|
|
11480
|
+
};
|
|
11481
|
+
reportProgress(0);
|
|
11482
|
+
try {
|
|
11483
|
+
reportProgress(5);
|
|
11484
|
+
const highs = await loadHiGHS();
|
|
11485
|
+
reportProgress(10);
|
|
11486
|
+
const complexity = analyzeProblemComplexity(problem);
|
|
11487
|
+
const viability = estimateViability(complexity);
|
|
11488
|
+
if (complexity.binaryVars > MAX_BINARY_VARS) {
|
|
11489
|
+
throw new Error(`Problem has too many binary variables for HiGHS WASM: ${complexity.binaryVars} (max ${MAX_BINARY_VARS}). Tip: More machines spreads ops and reduces binary vars. Current: ${complexity.numMachines} machines. For this size, use Simulated Annealing or Tabu Search.`);
|
|
11490
|
+
}
|
|
11491
|
+
if (complexity.totalOps > MAX_TOTAL_OPS) {
|
|
11492
|
+
throw new Error(`Problem too large for HiGHS WASM: ${complexity.totalOps} operations (max ${MAX_TOTAL_OPS}). For larger problems, use Simulated Annealing or Tabu Search.`);
|
|
11493
|
+
}
|
|
11494
|
+
if (complexity.opsPerMachine.max > MAX_OPS_PER_MACHINE) {
|
|
11495
|
+
throw new Error(`Too many operations on one machine: ${complexity.opsPerMachine.max} ops (max ${MAX_OPS_PER_MACHINE}). Tip: Add more machines to spread the load. For this size, use Simulated Annealing or Tabu Search.`);
|
|
11496
|
+
}
|
|
11497
|
+
if (viability.risk === "high") {
|
|
11498
|
+
console.warn(`[HiGHS] Warning: ${viability.recommendation}`);
|
|
11499
|
+
}
|
|
11500
|
+
reportProgress(15);
|
|
11501
|
+
const lpString = generateLPFormulation(problem);
|
|
11502
|
+
if (!lpString.includes("Subject To") || !lpString.includes("Bounds")) {
|
|
11503
|
+
throw new Error("Invalid LP formulation - missing required sections");
|
|
11504
|
+
}
|
|
11505
|
+
reportProgress(20);
|
|
11506
|
+
let solution;
|
|
11507
|
+
try {
|
|
11508
|
+
solution = highs.solve(lpString, {
|
|
11509
|
+
time_limit: options?.timeoutMs ? options.timeoutMs / 1e3 : 60,
|
|
11510
|
+
mip_rel_gap: 0,
|
|
11511
|
+
presolve: "on",
|
|
11512
|
+
log_to_console: true,
|
|
11513
|
+
// MUST BE TRUE - see file header
|
|
11514
|
+
output_flag: true
|
|
11515
|
+
// MUST BE TRUE - see file header
|
|
11516
|
+
});
|
|
11517
|
+
} catch (solveError) {
|
|
11518
|
+
console.error("[HiGHS] Solve error:", solveError);
|
|
11519
|
+
console.error("[HiGHS] Problem config:", {
|
|
11520
|
+
jobs: problem.jobs.length,
|
|
11521
|
+
machines: problem.machines.length,
|
|
11522
|
+
totalOps: problem.jobs.reduce((sum2, j) => sum2 + j.operations.length, 0)
|
|
11523
|
+
});
|
|
11524
|
+
const errMsg = solveError instanceof Error ? solveError.message : String(solveError);
|
|
11525
|
+
if (errMsg.includes("Aborted")) {
|
|
11526
|
+
throw new Error(`HiGHS WASM crashed. This may be a numerical issue with the problem configuration. Jobs: ${problem.jobs.length}, Machines: ${problem.machines.length}. Check browser console for details.`);
|
|
11527
|
+
}
|
|
11528
|
+
throw solveError;
|
|
11529
|
+
}
|
|
11530
|
+
if (solution.Status === "Infeasible") {
|
|
11531
|
+
throw new Error("Problem is infeasible - check constraints");
|
|
11532
|
+
}
|
|
11533
|
+
if (solution.Status === "Unbounded") {
|
|
11534
|
+
throw new Error("Problem is unbounded - check objective");
|
|
11535
|
+
}
|
|
11536
|
+
if (solution.Status !== "Optimal" && solution.Status !== "Time limit reached" && solution.Status !== "Bound on objective reached") {
|
|
11537
|
+
throw new Error(`HiGHS returned unexpected status: ${solution.Status}`);
|
|
11538
|
+
}
|
|
11539
|
+
reportProgress(90);
|
|
11540
|
+
const schedule = parseSolution(problem, solution.Columns);
|
|
11541
|
+
const makespan = Math.ceil(solution.ObjectiveValue);
|
|
11542
|
+
const validation = validateSchedule(problem, schedule);
|
|
11543
|
+
if (!validation.valid) {
|
|
11544
|
+
console.warn("[HiGHS] Solution validation failed:", validation.errors);
|
|
11545
|
+
const errorDetails = validation.errors && validation.errors.length > 0 ? validation.errors.join("; ") : "Unknown validation error";
|
|
11546
|
+
throw new Error(`[HiGHS] Solution validation failed: ${errorDetails}`);
|
|
11547
|
+
}
|
|
11548
|
+
reportProgress(100, makespan);
|
|
11549
|
+
return {
|
|
11550
|
+
solverId: "highs",
|
|
11551
|
+
solverName: "HiGHS (WASM)",
|
|
11552
|
+
makespan,
|
|
11553
|
+
schedule,
|
|
11554
|
+
elapsedMs: elapsed(startTime),
|
|
11555
|
+
iterations: 1
|
|
11556
|
+
};
|
|
11557
|
+
} catch (error) {
|
|
11558
|
+
reportProgress(0);
|
|
11559
|
+
throw error;
|
|
11560
|
+
}
|
|
11561
|
+
}
|
|
11562
|
+
};
|
|
11563
|
+
|
|
11199
11564
|
// ../../b4m-core/packages/quantum/dist/src/solvers/metadata.js
|
|
11200
11565
|
var solverMetadata = {
|
|
11201
11566
|
naive: {
|
|
@@ -11464,7 +11829,6 @@ var solverMetadata = {
|
|
|
11464
11829
|
color: "success",
|
|
11465
11830
|
complexity: "Seconds to minutes",
|
|
11466
11831
|
requires: "Browser compute (WASM)",
|
|
11467
|
-
available: false,
|
|
11468
11832
|
tagline: "Open-source solver rivaling commercial giants",
|
|
11469
11833
|
fullDescription: "HiGHS (High-performance Interior-point, Gradient-descent, Simplex) is an MIT-licensed open-source solver that achieves 90%+ of commercial solver performance. Developed at the University of Edinburgh, it has rapidly become the leading open-source alternative to Gurobi and COPT for linear and mixed-integer programming.",
|
|
11470
11834
|
howItWorks: [
|
|
@@ -11538,7 +11902,10 @@ var solverMetadata = {
|
|
|
11538
11902
|
wikipedia: "https://en.wikipedia.org/wiki/Quantum_approximate_optimization_algorithm",
|
|
11539
11903
|
otherResources: [
|
|
11540
11904
|
{ label: "Farhi et al. (2014) \u2014 Original QAOA Paper", url: "https://arxiv.org/abs/1411.4028" },
|
|
11541
|
-
{
|
|
11905
|
+
{
|
|
11906
|
+
label: "QUBO Formulation Guide",
|
|
11907
|
+
url: "https://en.wikipedia.org/wiki/Quadratic_unconstrained_binary_optimization"
|
|
11908
|
+
}
|
|
11542
11909
|
]
|
|
11543
11910
|
},
|
|
11544
11911
|
"ionq-qaoa": {
|
|
@@ -11596,7 +11963,8 @@ var allSolvers = [
|
|
|
11596
11963
|
simulatedAnnealingLargeSolver,
|
|
11597
11964
|
tabuSolver,
|
|
11598
11965
|
geneticAlgorithmSolver,
|
|
11599
|
-
antColonySolver
|
|
11966
|
+
antColonySolver,
|
|
11967
|
+
highsSolver
|
|
11600
11968
|
];
|
|
11601
11969
|
var solverRegistry = new Map(allSolvers.map((s) => [s.id, s]));
|
|
11602
11970
|
function getSolver(id) {
|
|
@@ -11607,7 +11975,6 @@ function getAvailableSolverIds() {
|
|
|
11607
11975
|
}
|
|
11608
11976
|
var displaySolvers = [
|
|
11609
11977
|
...allSolvers.map((s) => ({ id: s.id, name: s.name, description: s.description })),
|
|
11610
|
-
{ id: "highs", name: "HiGHS (WASM)", description: solverMetadata.highs.tagline },
|
|
11611
11978
|
{ id: "simulated-qaoa", name: "Simulated QAOA", description: solverMetadata["simulated-qaoa"].tagline },
|
|
11612
11979
|
{ id: "ionq-qaoa", name: "IonQ QAOA", description: solverMetadata["ionq-qaoa"].tagline }
|
|
11613
11980
|
];
|
|
@@ -11632,11 +11999,17 @@ ${allSolvers.map((s) => `- **${s.name}** (\`${s.id}\`): ${s.description}`).join(
|
|
|
11632
11999
|
|
|
11633
12000
|
## How to Help Users
|
|
11634
12001
|
|
|
11635
|
-
###
|
|
11636
|
-
When a user describes a scheduling
|
|
11637
|
-
1. Use \`quantum_formulate\` to convert their description into
|
|
11638
|
-
2.
|
|
11639
|
-
3.
|
|
12002
|
+
### Concierge Flow (Default)
|
|
12003
|
+
When a user describes a scheduling problem:
|
|
12004
|
+
1. Use \`quantum_formulate\` to convert their description \u2014 the problem auto-loads into the Problem Editor
|
|
12005
|
+
2. Call \`navigate_view\` with viewId "opti.scheduling.problem" so the user gets a button to open the Problem tab
|
|
12006
|
+
3. Let the user review, tweak machines/durations, and run solvers from the dashboard
|
|
12007
|
+
Do NOT auto-call \`quantum_schedule\` unless the user explicitly asks to solve in chat.
|
|
12008
|
+
|
|
12009
|
+
### Power User Fast Path
|
|
12010
|
+
If the user says "solve it", "find the optimal schedule", or explicitly requests an in-chat solution,
|
|
12011
|
+
use both \`quantum_formulate\` AND \`quantum_schedule\`. The problem still loads into the Editor
|
|
12012
|
+
so the user can explore results in the dashboard too.
|
|
11640
12013
|
|
|
11641
12014
|
### Running Solvers
|
|
11642
12015
|
When solving a problem:
|
|
@@ -11701,6 +12074,581 @@ RESPOND WITH ONLY A JSON OBJECT matching this schema:
|
|
|
11701
12074
|
|
|
11702
12075
|
No markdown, no explanation, no code blocks \u2014 just the raw JSON object.`;
|
|
11703
12076
|
|
|
12077
|
+
// ../../b4m-core/packages/quantum/dist/src/patterns.js
|
|
12078
|
+
var patternFamilies = [
|
|
12079
|
+
{
|
|
12080
|
+
id: "scheduling",
|
|
12081
|
+
name: "Scheduling",
|
|
12082
|
+
description: "Job shop, flow shop, resource allocation over time",
|
|
12083
|
+
complexity: "NP-hard",
|
|
12084
|
+
color: "#e53935",
|
|
12085
|
+
quboFit: "excellent",
|
|
12086
|
+
examples: ["Job Shop Scheduling", "Task Scheduling", "Production Planning"],
|
|
12087
|
+
status: "available",
|
|
12088
|
+
tagline: "When to do things, in what order, on what resources",
|
|
12089
|
+
asciiDiagram: [
|
|
12090
|
+
" 0 2 4 6 8 10 12",
|
|
12091
|
+
" \u251C\u2500\u2500\u253C\u2500\u2500\u253C\u2500\u2500\u253C\u2500\u2500\u253C\u2500\u2500\u253C\u2500\u2500\u2524",
|
|
12092
|
+
"A [\u25A0\u25A0\u25A0\u25A0\u25A0][ \u2591\u2591\u2591\u2591\u2591\u2591 ]",
|
|
12093
|
+
"B [\u2591\u2591\u2591\u2591\u2591][ \u25A0\u25A0\u25A0\u25A0\u25A0 ]",
|
|
12094
|
+
"C [\u25A0\u25A0\u25A0] [\u2591\u2591\u2591\u2591\u2591\u2591]",
|
|
12095
|
+
" \u2500\u2500\u2500\u2500 time \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25BA"
|
|
12096
|
+
].join("\n"),
|
|
12097
|
+
subPatterns: [
|
|
12098
|
+
{
|
|
12099
|
+
name: "Job Shop Scheduling",
|
|
12100
|
+
subtitle: "The Classic",
|
|
12101
|
+
description: "Assign jobs to machines with precedence constraints. Each job has a sequence of operations that must be processed on specific machines in order. The goal is to minimize the total makespan.",
|
|
12102
|
+
asciiDiagram: [
|
|
12103
|
+
"J1: [M-A 3t]->[M-B 2t]->[M-C 4t]",
|
|
12104
|
+
"J2: [M-B 2t]->[M-C 3t]->[M-A 2t]",
|
|
12105
|
+
"J3: [M-C 4t]->[M-A 1t]->[M-B 3t]",
|
|
12106
|
+
"",
|
|
12107
|
+
"Objective: Minimize total completion time"
|
|
12108
|
+
].join("\n"),
|
|
12109
|
+
quboFitStars: 5
|
|
12110
|
+
},
|
|
12111
|
+
{
|
|
12112
|
+
name: "Flow Shop Scheduling",
|
|
12113
|
+
subtitle: "Fixed Sequence",
|
|
12114
|
+
description: "All jobs follow the same machine order. Simpler than job shop but still NP-hard for 3+ machines. Common in assembly lines and manufacturing pipelines.",
|
|
12115
|
+
asciiDiagram: [
|
|
12116
|
+
"Job 1: -->[M1]-->[M2]-->[M3]--> Done",
|
|
12117
|
+
"Job 2: -->[M1]-->[M2]-->[M3]--> Done",
|
|
12118
|
+
"Job 3: -->[M1]-->[M2]-->[M3]--> Done",
|
|
12119
|
+
" Fixed order through all machines"
|
|
12120
|
+
].join("\n"),
|
|
12121
|
+
quboFitStars: 5
|
|
12122
|
+
},
|
|
12123
|
+
{
|
|
12124
|
+
name: "Timetabling",
|
|
12125
|
+
subtitle: "Conflict Avoidance",
|
|
12126
|
+
description: "Schedule events into time slots while avoiding conflicts. No professor teaches two classes at once, no student has overlapping classes, room capacities are respected.",
|
|
12127
|
+
asciiDiagram: [
|
|
12128
|
+
" Mon Tue Wed Thu",
|
|
12129
|
+
" 9:00 |CS101| |CS101| |",
|
|
12130
|
+
"10:00 | |MATH | |MATH |",
|
|
12131
|
+
"11:00 |PHYS | |PHYS | |",
|
|
12132
|
+
" No conflicts for shared resources!"
|
|
12133
|
+
].join("\n"),
|
|
12134
|
+
quboFitStars: 4
|
|
12135
|
+
},
|
|
12136
|
+
{
|
|
12137
|
+
name: "Sequencing with Changeover",
|
|
12138
|
+
subtitle: "Order Matters",
|
|
12139
|
+
description: "Transition costs between tasks depend on the sequence. Paint lines minimize cleaning by ordering light-to-dark. Semiconductor fabs batch similar wafers together.",
|
|
12140
|
+
asciiDiagram: [
|
|
12141
|
+
"White->Yellow->Orange $0 each",
|
|
12142
|
+
"Orange->Red->Black $0 each",
|
|
12143
|
+
"White->Black directly $50 clean!",
|
|
12144
|
+
"",
|
|
12145
|
+
"Objective: Minimize total changeover cost"
|
|
12146
|
+
].join("\n"),
|
|
12147
|
+
quboFitStars: 4
|
|
12148
|
+
},
|
|
12149
|
+
{
|
|
12150
|
+
name: "Dynamic Scheduling",
|
|
12151
|
+
subtitle: "Continuous Arrival",
|
|
12152
|
+
description: "New jobs arrive during execution, requiring real-time rescheduling. Common in hospitals, data centers, and cloud computing where demand is unpredictable.",
|
|
12153
|
+
asciiDiagram: [
|
|
12154
|
+
"Time --------------------------->",
|
|
12155
|
+
"J1 ========",
|
|
12156
|
+
" J2 ==========",
|
|
12157
|
+
" J3 ======= (arrived t=3)",
|
|
12158
|
+
" J4 === (arrived t=5)",
|
|
12159
|
+
" Must reschedule as jobs arrive!"
|
|
12160
|
+
].join("\n"),
|
|
12161
|
+
quboFitStars: 3
|
|
12162
|
+
}
|
|
12163
|
+
],
|
|
12164
|
+
quboExplainer: "Each binary variable x(j,m,t) = 1 if job j starts on machine m at time t. Penalty terms enforce: (1) each operation scheduled exactly once, (2) precedence constraints respected, (3) no machine processes two jobs simultaneously. Qubit count scales as O(jobs x machines x time_horizon).",
|
|
12165
|
+
useCases: [
|
|
12166
|
+
{ industry: "Manufacturing", application: "Factory floor scheduling" },
|
|
12167
|
+
{ industry: "Healthcare", application: "Operating room scheduling" },
|
|
12168
|
+
{ industry: "Airlines", application: "Crew and gate scheduling" },
|
|
12169
|
+
{ industry: "Data Centers", application: "Batch job scheduling" },
|
|
12170
|
+
{ industry: "Construction", application: "Project task sequencing" },
|
|
12171
|
+
{ industry: "Restaurants", application: "Kitchen order optimization" }
|
|
12172
|
+
]
|
|
12173
|
+
},
|
|
12174
|
+
{
|
|
12175
|
+
id: "routing",
|
|
12176
|
+
name: "Routing",
|
|
12177
|
+
description: "Vehicle routing, TSP, network path optimization",
|
|
12178
|
+
complexity: "NP-hard",
|
|
12179
|
+
color: "#66bb6a",
|
|
12180
|
+
quboFit: "excellent",
|
|
12181
|
+
examples: ["Traveling Salesman", "Vehicle Routing", "Delivery Optimization"],
|
|
12182
|
+
status: "coming-soon",
|
|
12183
|
+
tagline: "How to move through space efficiently",
|
|
12184
|
+
asciiDiagram: [
|
|
12185
|
+
" A",
|
|
12186
|
+
" /|\\",
|
|
12187
|
+
" 5/ | \\3",
|
|
12188
|
+
" / | \\",
|
|
12189
|
+
" B---+---C",
|
|
12190
|
+
" \\ | /",
|
|
12191
|
+
" 7\\ | /2",
|
|
12192
|
+
" \\|/",
|
|
12193
|
+
" D"
|
|
12194
|
+
].join("\n"),
|
|
12195
|
+
subPatterns: [
|
|
12196
|
+
{
|
|
12197
|
+
name: "Traveling Salesman (TSP)",
|
|
12198
|
+
subtitle: "The Classic",
|
|
12199
|
+
description: "Visit all cities exactly once and return home via the shortest route. One of the most famous optimization problems \u2014 100+ cities makes exhaustive search impossible.",
|
|
12200
|
+
asciiDiagram: [
|
|
12201
|
+
"Start -> A -> B -> C -> D -> Start",
|
|
12202
|
+
"",
|
|
12203
|
+
"Find the shortest tour that visits",
|
|
12204
|
+
"every city exactly once!"
|
|
12205
|
+
].join("\n"),
|
|
12206
|
+
quboFitStars: 5
|
|
12207
|
+
},
|
|
12208
|
+
{
|
|
12209
|
+
name: "Vehicle Routing (VRP)",
|
|
12210
|
+
subtitle: "Multiple Vehicles",
|
|
12211
|
+
description: "Partition customers among a fleet of vehicles, each with capacity limits and time windows. TSP generalized to multiple routes from a central depot.",
|
|
12212
|
+
asciiDiagram: [
|
|
12213
|
+
" Depot",
|
|
12214
|
+
" / | \\",
|
|
12215
|
+
" / | \\",
|
|
12216
|
+
" Route1 Route2 Route3",
|
|
12217
|
+
" A->B D->E G->H",
|
|
12218
|
+
" ->C ->F ->I"
|
|
12219
|
+
].join("\n"),
|
|
12220
|
+
quboFitStars: 4
|
|
12221
|
+
},
|
|
12222
|
+
{
|
|
12223
|
+
name: "Shortest Path",
|
|
12224
|
+
subtitle: "Point-to-Point",
|
|
12225
|
+
description: "Find the minimum-cost path between two nodes in a weighted graph. Foundation for GPS navigation, network routing, and supply chain logistics.",
|
|
12226
|
+
asciiDiagram: [
|
|
12227
|
+
"S --3-- A --2-- T",
|
|
12228
|
+
"| | |",
|
|
12229
|
+
"5 1 4",
|
|
12230
|
+
"| | |",
|
|
12231
|
+
"B --6-- C --2-- D"
|
|
12232
|
+
].join("\n"),
|
|
12233
|
+
quboFitStars: 3
|
|
12234
|
+
}
|
|
12235
|
+
],
|
|
12236
|
+
quboExplainer: "Binary variable x(i,t) = 1 if city i is visited at step t. Constraints: each city visited exactly once, each step visits exactly one city. Objective minimizes total edge weights along the tour. Classic QUBO formulation.",
|
|
12237
|
+
useCases: [
|
|
12238
|
+
{ industry: "Logistics", application: "Delivery route optimization" },
|
|
12239
|
+
{ industry: "Ride-sharing", application: "Driver dispatch routing" },
|
|
12240
|
+
{ industry: "Telecom", application: "Network packet routing" },
|
|
12241
|
+
{ industry: "Retail", application: "Supply chain distribution" },
|
|
12242
|
+
{ industry: "Field Service", application: "Technician visit scheduling" }
|
|
12243
|
+
]
|
|
12244
|
+
},
|
|
12245
|
+
{
|
|
12246
|
+
id: "packing",
|
|
12247
|
+
name: "Packing",
|
|
12248
|
+
description: "Bin packing, knapsack, container optimization",
|
|
12249
|
+
complexity: "NP-complete",
|
|
12250
|
+
color: "#e91e63",
|
|
12251
|
+
quboFit: "good",
|
|
12252
|
+
examples: ["Bin Packing", "Knapsack Problem", "Container Loading"],
|
|
12253
|
+
status: "coming-soon",
|
|
12254
|
+
tagline: "How to fit things into space efficiently",
|
|
12255
|
+
asciiDiagram: [
|
|
12256
|
+
"\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510",
|
|
12257
|
+
"\u2502 \u2588\u2588\u2588\u2588 \u2591\u2591\u2591\u2591 \u2588\u2588\u2588\u2588\u2588\u2588 \u2502 92%",
|
|
12258
|
+
"\u2502 \u2588\u2588\u2588\u2588 \u2591\u2591\u2591\u2591 \u2588\u2588\u2588\u2588\u2588\u2588 \u2502",
|
|
12259
|
+
"\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524",
|
|
12260
|
+
"\u2502 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2502 68%",
|
|
12261
|
+
"\u2502 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2591\u2591\u2591\u2591\u2591\u2591\u2591 \u2502",
|
|
12262
|
+
"\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"
|
|
12263
|
+
].join("\n"),
|
|
12264
|
+
subPatterns: [
|
|
12265
|
+
{
|
|
12266
|
+
name: "Bin Packing",
|
|
12267
|
+
subtitle: "1D/2D/3D",
|
|
12268
|
+
description: "Fit items into the minimum number of bins. 1D (rod cutting, memory), 2D (sheet cutting, floor plans), 3D (container loading, truck packing). Items arrive online or in batch.",
|
|
12269
|
+
asciiDiagram: [
|
|
12270
|
+
"Items: [3] [5] [2] [4] [6]",
|
|
12271
|
+
"",
|
|
12272
|
+
"Bin 1: [3][5][2] = 10/10",
|
|
12273
|
+
"Bin 2: [4][6] = 10/10",
|
|
12274
|
+
"Minimum bins: 2"
|
|
12275
|
+
].join("\n"),
|
|
12276
|
+
quboFitStars: 4
|
|
12277
|
+
},
|
|
12278
|
+
{
|
|
12279
|
+
name: "Knapsack",
|
|
12280
|
+
subtitle: "Value vs Weight",
|
|
12281
|
+
description: "Select items to maximize total value without exceeding weight capacity. The 0/1 knapsack is a direct binary problem \u2014 include or exclude each item.",
|
|
12282
|
+
asciiDiagram: [
|
|
12283
|
+
"Item Value Weight",
|
|
12284
|
+
" A 60 10",
|
|
12285
|
+
" B 100 20 <-- pick",
|
|
12286
|
+
" C 120 30 <-- pick",
|
|
12287
|
+
"Capacity: 50 Best: $220"
|
|
12288
|
+
].join("\n"),
|
|
12289
|
+
quboFitStars: 5
|
|
12290
|
+
},
|
|
12291
|
+
{
|
|
12292
|
+
name: "Cutting Stock",
|
|
12293
|
+
subtitle: "Minimize Waste",
|
|
12294
|
+
description: "Cut raw material (steel rolls, fabric bolts, lumber) into required pieces with minimal waste. Dual of bin packing \u2014 subtract from fixed-size stock.",
|
|
12295
|
+
asciiDiagram: [
|
|
12296
|
+
"Stock roll: |============|",
|
|
12297
|
+
"Cut: |==A==|==B==|=C=|xx|",
|
|
12298
|
+
" waste",
|
|
12299
|
+
"Objective: Minimize total waste"
|
|
12300
|
+
].join("\n"),
|
|
12301
|
+
quboFitStars: 4
|
|
12302
|
+
}
|
|
12303
|
+
],
|
|
12304
|
+
quboExplainer: "Binary variable x(i,b) = 1 if item i is placed in bin b. Constraints: each item in exactly one bin, bin capacity not exceeded. For knapsack, x(i) = 1 if item i is selected, with weight constraint as penalty term.",
|
|
12305
|
+
useCases: [
|
|
12306
|
+
{ industry: "Shipping", application: "Container loading optimization" },
|
|
12307
|
+
{ industry: "Manufacturing", application: "Raw material cutting" },
|
|
12308
|
+
{ industry: "Cloud Computing", application: "VM placement on servers" },
|
|
12309
|
+
{ industry: "Retail", application: "Warehouse space allocation" },
|
|
12310
|
+
{ industry: "Finance", application: "Budget allocation (knapsack)" }
|
|
12311
|
+
]
|
|
12312
|
+
},
|
|
12313
|
+
{
|
|
12314
|
+
id: "assignment",
|
|
12315
|
+
name: "Assignment",
|
|
12316
|
+
description: "Matching agents to tasks, resource allocation",
|
|
12317
|
+
complexity: "NP-complete",
|
|
12318
|
+
color: "#42a5f5",
|
|
12319
|
+
quboFit: "excellent",
|
|
12320
|
+
examples: ["Task Assignment", "Resource Matching", "Workforce Allocation"],
|
|
12321
|
+
status: "coming-soon",
|
|
12322
|
+
tagline: "Who does what \u2014 optimal matching",
|
|
12323
|
+
asciiDiagram: [
|
|
12324
|
+
" Agents Tasks",
|
|
12325
|
+
" [A] \u2500\u2500\u2500\u2500\u2500\u2500 [1]",
|
|
12326
|
+
" [B] \u2500\u2500\u2510",
|
|
12327
|
+
" \u2514\u2500\u2500 [2]",
|
|
12328
|
+
" [C] \u2500\u2500\u2500\u2500\u2500\u2500 [3]",
|
|
12329
|
+
" [D] \u2500\u2500\u2500\u2500\u2500\u2500 [4]"
|
|
12330
|
+
].join("\n"),
|
|
12331
|
+
subPatterns: [
|
|
12332
|
+
{
|
|
12333
|
+
name: "Bipartite Matching",
|
|
12334
|
+
subtitle: "One-to-One",
|
|
12335
|
+
description: "Match agents to tasks where each agent handles exactly one task and vice versa. Minimize total cost or maximize total benefit across all assignments.",
|
|
12336
|
+
asciiDiagram: [
|
|
12337
|
+
"Workers Jobs",
|
|
12338
|
+
" Alice ---> Design cost: 3",
|
|
12339
|
+
" Bob -----> Code cost: 2",
|
|
12340
|
+
" Carol ---> Test cost: 4",
|
|
12341
|
+
"Total cost: 9 (optimal)"
|
|
12342
|
+
].join("\n"),
|
|
12343
|
+
quboFitStars: 5
|
|
12344
|
+
},
|
|
12345
|
+
{
|
|
12346
|
+
name: "Quadratic Assignment",
|
|
12347
|
+
subtitle: "Location Matters",
|
|
12348
|
+
description: "Assign facilities to locations minimizing the product of flow between facilities and distance between locations. Used for factory layout and chip placement.",
|
|
12349
|
+
asciiDiagram: [
|
|
12350
|
+
"Facility Flow Location Dist",
|
|
12351
|
+
" A <-50-> B L1 <-3-> L2",
|
|
12352
|
+
" A <-20-> C L1 <-5-> L3",
|
|
12353
|
+
"Minimize: sum(flow*distance)"
|
|
12354
|
+
].join("\n"),
|
|
12355
|
+
quboFitStars: 5
|
|
12356
|
+
},
|
|
12357
|
+
{
|
|
12358
|
+
name: "Generalized Assignment",
|
|
12359
|
+
subtitle: "Many-to-One",
|
|
12360
|
+
description: "Assign tasks to agents where each agent can handle multiple tasks within their capacity. Workers have different skills and capacities across task types.",
|
|
12361
|
+
asciiDiagram: [
|
|
12362
|
+
"Agent A (cap 10): [T1:3][T2:4][T3:3]",
|
|
12363
|
+
"Agent B (cap 8): [T4:5][T5:3]",
|
|
12364
|
+
"Agent C (cap 12): [T6:6][T7:4]",
|
|
12365
|
+
"Maximize quality within capacity"
|
|
12366
|
+
].join("\n"),
|
|
12367
|
+
quboFitStars: 4
|
|
12368
|
+
}
|
|
12369
|
+
],
|
|
12370
|
+
quboExplainer: "Binary variable x(i,j) = 1 if agent i is assigned to task j. Constraints: each task assigned to exactly one agent (row sums = 1), each agent at most one task (column sums <= 1). Cost matrix entries become QUBO coefficients.",
|
|
12371
|
+
useCases: [
|
|
12372
|
+
{ industry: "HR", application: "Employee-to-project matching" },
|
|
12373
|
+
{ industry: "Education", application: "Student-to-course assignment" },
|
|
12374
|
+
{ industry: "Healthcare", application: "Doctor-to-shift assignment" },
|
|
12375
|
+
{ industry: "Military", application: "Weapon-target assignment" },
|
|
12376
|
+
{ industry: "Sports", application: "Referee-to-game assignment" }
|
|
12377
|
+
]
|
|
12378
|
+
},
|
|
12379
|
+
{
|
|
12380
|
+
id: "network",
|
|
12381
|
+
name: "Network",
|
|
12382
|
+
description: "Graph partitioning, max cut, community detection",
|
|
12383
|
+
complexity: "NP-hard",
|
|
12384
|
+
color: "#f4511e",
|
|
12385
|
+
quboFit: "excellent",
|
|
12386
|
+
examples: ["Graph Partitioning", "Max Cut", "Network Design"],
|
|
12387
|
+
status: "coming-soon",
|
|
12388
|
+
tagline: "How to structure and divide networks",
|
|
12389
|
+
asciiDiagram: [
|
|
12390
|
+
" a-b-c | d-e",
|
|
12391
|
+
" | | | | |",
|
|
12392
|
+
" f-g | h-i",
|
|
12393
|
+
" -------+-------",
|
|
12394
|
+
" Group A | Group B",
|
|
12395
|
+
" max cut \u2702"
|
|
12396
|
+
].join("\n"),
|
|
12397
|
+
subPatterns: [
|
|
12398
|
+
{
|
|
12399
|
+
name: "Max Cut",
|
|
12400
|
+
subtitle: "The QUBO Natural",
|
|
12401
|
+
description: "Partition graph nodes into two groups to maximize edges crossing the cut. The most natural QUBO problem \u2014 maps directly without any reformulation tricks.",
|
|
12402
|
+
asciiDiagram: [
|
|
12403
|
+
"Group 0 | Group 1",
|
|
12404
|
+
" a--b | d--e",
|
|
12405
|
+
" | | |",
|
|
12406
|
+
" c ------+------ f",
|
|
12407
|
+
" cut edges = 3 (max!)"
|
|
12408
|
+
].join("\n"),
|
|
12409
|
+
quboFitStars: 5
|
|
12410
|
+
},
|
|
12411
|
+
{
|
|
12412
|
+
name: "Graph Partitioning",
|
|
12413
|
+
subtitle: "Balanced Split",
|
|
12414
|
+
description: "Divide nodes into k equal-sized groups minimizing edges between groups. Used for parallel computing load balancing and VLSI chip layout.",
|
|
12415
|
+
asciiDiagram: [
|
|
12416
|
+
"Before: tangled graph",
|
|
12417
|
+
"After: [ A ] | [ B ] | [ C ]",
|
|
12418
|
+
" n/3 | n/3 | n/3",
|
|
12419
|
+
"Minimize cross-partition edges"
|
|
12420
|
+
].join("\n"),
|
|
12421
|
+
quboFitStars: 5
|
|
12422
|
+
},
|
|
12423
|
+
{
|
|
12424
|
+
name: "Community Detection",
|
|
12425
|
+
subtitle: "Find Clusters",
|
|
12426
|
+
description: "Discover densely connected groups within a network. Social networks, protein interactions, citation graphs. Related to modularity maximization.",
|
|
12427
|
+
asciiDiagram: [
|
|
12428
|
+
"(a-b-c) (d-e-f)",
|
|
12429
|
+
" dense dense",
|
|
12430
|
+
" \\ /",
|
|
12431
|
+
" sparse",
|
|
12432
|
+
"Find the natural communities"
|
|
12433
|
+
].join("\n"),
|
|
12434
|
+
quboFitStars: 4
|
|
12435
|
+
}
|
|
12436
|
+
],
|
|
12437
|
+
quboExplainer: "For Max Cut: x(i) = 0 or 1 assigns node i to a group. Objective maximizes sum of w(i,j) * x(i) * (1-x(j)) over all edges. This is already a QUBO \u2014 no reformulation needed! Graph partitioning adds a balance constraint as a penalty term.",
|
|
12438
|
+
useCases: [
|
|
12439
|
+
{ industry: "Social Media", application: "Community detection" },
|
|
12440
|
+
{ industry: "VLSI Design", application: "Chip layout partitioning" },
|
|
12441
|
+
{ industry: "HPC", application: "Parallel workload balancing" },
|
|
12442
|
+
{ industry: "Biology", application: "Protein interaction clustering" },
|
|
12443
|
+
{ industry: "Telecom", application: "Network segmentation" }
|
|
12444
|
+
]
|
|
12445
|
+
},
|
|
12446
|
+
{
|
|
12447
|
+
id: "selection",
|
|
12448
|
+
name: "Selection",
|
|
12449
|
+
description: "Portfolio optimization, feature selection, subset problems",
|
|
12450
|
+
complexity: "NP-complete",
|
|
12451
|
+
color: "#00897b",
|
|
12452
|
+
quboFit: "good",
|
|
12453
|
+
examples: ["Portfolio Selection", "Feature Selection", "Subset Sum"],
|
|
12454
|
+
status: "coming-soon",
|
|
12455
|
+
tagline: "Which items to choose from a set",
|
|
12456
|
+
asciiDiagram: [
|
|
12457
|
+
" [\u25A0] [\xB7] [\u25A0] [\xB7]",
|
|
12458
|
+
" [\xB7] [\u25A0] [\xB7] [\u25A0]",
|
|
12459
|
+
" [\u25A0] [\xB7] [\xB7] [\xB7]",
|
|
12460
|
+
" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
12461
|
+
" \u25A0 = selected 5/12",
|
|
12462
|
+
" score: 847 / 1000"
|
|
12463
|
+
].join("\n"),
|
|
12464
|
+
subPatterns: [
|
|
12465
|
+
{
|
|
12466
|
+
name: "Portfolio Optimization",
|
|
12467
|
+
subtitle: "Risk vs Return",
|
|
12468
|
+
description: "Select assets to maximize return while minimizing risk (variance). Markowitz model is naturally quadratic \u2014 covariance matrix maps directly to QUBO interactions.",
|
|
12469
|
+
asciiDiagram: [
|
|
12470
|
+
"Return ^",
|
|
12471
|
+
" | * efficient frontier",
|
|
12472
|
+
" | *",
|
|
12473
|
+
" | * <- optimal portfolio",
|
|
12474
|
+
" |* ",
|
|
12475
|
+
" +---------> Risk"
|
|
12476
|
+
].join("\n"),
|
|
12477
|
+
quboFitStars: 5
|
|
12478
|
+
},
|
|
12479
|
+
{
|
|
12480
|
+
name: "Feature Selection",
|
|
12481
|
+
subtitle: "Signal vs Noise",
|
|
12482
|
+
description: "Choose the best subset of features for a machine learning model. Too many features cause overfitting; too few miss signal. Binary choice per feature makes this naturally QUBO.",
|
|
12483
|
+
asciiDiagram: [
|
|
12484
|
+
"Features: [x1] [x2] [x3] ... [xN]",
|
|
12485
|
+
"Select: Y N Y ... N",
|
|
12486
|
+
"",
|
|
12487
|
+
"Maximize: accuracy - lambda*count"
|
|
12488
|
+
].join("\n"),
|
|
12489
|
+
quboFitStars: 4
|
|
12490
|
+
},
|
|
12491
|
+
{
|
|
12492
|
+
name: "Set Cover",
|
|
12493
|
+
subtitle: "Minimum Coverage",
|
|
12494
|
+
description: "Choose the fewest subsets that together cover all elements. Used for sensor placement, test suite minimization, and service location planning.",
|
|
12495
|
+
asciiDiagram: [
|
|
12496
|
+
"Universe: {1,2,3,4,5,6,7}",
|
|
12497
|
+
"S1={1,2,3} S2={2,4} S3={3,4,5}",
|
|
12498
|
+
"S4={5,6,7} S5={1,6}",
|
|
12499
|
+
"Solution: S1 + S3 + S4 (covers all)"
|
|
12500
|
+
].join("\n"),
|
|
12501
|
+
quboFitStars: 4
|
|
12502
|
+
}
|
|
12503
|
+
],
|
|
12504
|
+
quboExplainer: "Binary variable x(i) = 1 if item i is selected. For portfolio: minimize x^T * Sigma * x - lambda * mu^T * x where Sigma is covariance and mu is expected return. The quadratic form IS the QUBO \u2014 no conversion needed.",
|
|
12505
|
+
useCases: [
|
|
12506
|
+
{ industry: "Finance", application: "Portfolio construction" },
|
|
12507
|
+
{ industry: "Machine Learning", application: "Feature subset selection" },
|
|
12508
|
+
{ industry: "Telecom", application: "Cell tower placement" },
|
|
12509
|
+
{ industry: "Insurance", application: "Product bundle selection" },
|
|
12510
|
+
{ industry: "Military", application: "Sensor network deployment" }
|
|
12511
|
+
]
|
|
12512
|
+
},
|
|
12513
|
+
{
|
|
12514
|
+
id: "economic",
|
|
12515
|
+
name: "Economic",
|
|
12516
|
+
description: "Market equilibrium, auction design, pricing",
|
|
12517
|
+
complexity: "NP-hard",
|
|
12518
|
+
color: "#ab47bc",
|
|
12519
|
+
quboFit: "experimental",
|
|
12520
|
+
examples: ["Market Clearing", "Auction Optimization", "Price Discovery"],
|
|
12521
|
+
status: "coming-soon",
|
|
12522
|
+
tagline: "Finding optimal prices and market equilibria",
|
|
12523
|
+
asciiDiagram: [
|
|
12524
|
+
" P \u2502\\ /",
|
|
12525
|
+
" \u2502 \\ / Supply",
|
|
12526
|
+
" \u2502 \\/",
|
|
12527
|
+
" \u2502 /\\ \u2190 equilibrium",
|
|
12528
|
+
" \u2502 / \\",
|
|
12529
|
+
" \u2502/ \\ Demand",
|
|
12530
|
+
" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 Q"
|
|
12531
|
+
].join("\n"),
|
|
12532
|
+
subPatterns: [
|
|
12533
|
+
{
|
|
12534
|
+
name: "Market Clearing",
|
|
12535
|
+
subtitle: "Equilibrium",
|
|
12536
|
+
description: "Find prices where supply meets demand across multiple goods simultaneously. Power grid markets clear hourly; financial exchanges clear in microseconds.",
|
|
12537
|
+
asciiDiagram: [
|
|
12538
|
+
"Buyers: B1=$50 B2=$40 B3=$30",
|
|
12539
|
+
"Sellers: S1=$20 S2=$35 S3=$45",
|
|
12540
|
+
"Clear price: $35-40 (2 trades)",
|
|
12541
|
+
"Maximize social welfare"
|
|
12542
|
+
].join("\n"),
|
|
12543
|
+
quboFitStars: 3
|
|
12544
|
+
},
|
|
12545
|
+
{
|
|
12546
|
+
name: "Combinatorial Auction",
|
|
12547
|
+
subtitle: "Bundle Bidding",
|
|
12548
|
+
description: "Bidders submit bids on bundles of items. Winner determination maximizes revenue while ensuring each item sold at most once. Directly maps to weighted set packing.",
|
|
12549
|
+
asciiDiagram: [
|
|
12550
|
+
"Bid 1: {A,B} = $100",
|
|
12551
|
+
"Bid 2: {B,C} = $80",
|
|
12552
|
+
"Bid 3: {A} = $60",
|
|
12553
|
+
"Bid 4: {C} = $50",
|
|
12554
|
+
"Best: Bid 1 + Bid 4 = $150"
|
|
12555
|
+
].join("\n"),
|
|
12556
|
+
quboFitStars: 4
|
|
12557
|
+
},
|
|
12558
|
+
{
|
|
12559
|
+
name: "Pricing Optimization",
|
|
12560
|
+
subtitle: "Revenue Maximization",
|
|
12561
|
+
description: "Set prices across products to maximize total revenue considering demand elasticity, competition, and cross-product effects (substitutes and complements).",
|
|
12562
|
+
asciiDiagram: [
|
|
12563
|
+
"Price Demand Revenue",
|
|
12564
|
+
" $10 100 $1000",
|
|
12565
|
+
" $15 70 $1050 <- optimal",
|
|
12566
|
+
" $20 40 $800",
|
|
12567
|
+
" $25 15 $375"
|
|
12568
|
+
].join("\n"),
|
|
12569
|
+
quboFitStars: 2
|
|
12570
|
+
}
|
|
12571
|
+
],
|
|
12572
|
+
quboExplainer: "Auction winner determination: x(i) = 1 if bid i is accepted. Maximize sum of bid values. Constraint: for each item, sum of accepted bids containing that item <= 1. Requires discretizing continuous prices into binary tiers for QUBO encoding.",
|
|
12573
|
+
useCases: [
|
|
12574
|
+
{ industry: "Energy", application: "Power market clearing" },
|
|
12575
|
+
{ industry: "Advertising", application: "Ad auction optimization" },
|
|
12576
|
+
{ industry: "Spectrum", application: "FCC spectrum auctions" },
|
|
12577
|
+
{ industry: "Retail", application: "Dynamic pricing strategy" },
|
|
12578
|
+
{ industry: "Agriculture", application: "Commodity market design" }
|
|
12579
|
+
]
|
|
12580
|
+
},
|
|
12581
|
+
{
|
|
12582
|
+
id: "continuous",
|
|
12583
|
+
name: "Continuous",
|
|
12584
|
+
description: "Continuous optimization with discretization",
|
|
12585
|
+
complexity: "NP-hard",
|
|
12586
|
+
color: "#78909c",
|
|
12587
|
+
quboFit: "fair",
|
|
12588
|
+
examples: ["Parameter Tuning", "Function Optimization", "Calibration"],
|
|
12589
|
+
status: "coming-soon",
|
|
12590
|
+
tagline: "Finding the best point in continuous space",
|
|
12591
|
+
asciiDiagram: [
|
|
12592
|
+
" f(x)",
|
|
12593
|
+
" \u2502 \u2571\u2572",
|
|
12594
|
+
" \u2502 \u2571 \u2572 \u2571\u2572",
|
|
12595
|
+
" \u2502\u2571 \u2572 \u2571 \u2572",
|
|
12596
|
+
" \u2502 \u2573 \u2572",
|
|
12597
|
+
" \u2502 \u2191 min \u2572",
|
|
12598
|
+
" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 x"
|
|
12599
|
+
].join("\n"),
|
|
12600
|
+
subPatterns: [
|
|
12601
|
+
{
|
|
12602
|
+
name: "Parameter Tuning",
|
|
12603
|
+
subtitle: "Find the Sweet Spot",
|
|
12604
|
+
description: "Optimize continuous parameters (temperature, pressure, learning rate) by discretizing into binary-encoded levels. Each parameter gets log2(levels) qubits.",
|
|
12605
|
+
asciiDiagram: [
|
|
12606
|
+
"Param A: [0.1, 0.2, 0.3, 0.4]",
|
|
12607
|
+
"Param B: [10, 20, 30, 40, 50]",
|
|
12608
|
+
"",
|
|
12609
|
+
"Encode: 2 bits per param (4 levels)",
|
|
12610
|
+
"Search 4x5 = 20 combinations"
|
|
12611
|
+
].join("\n"),
|
|
12612
|
+
quboFitStars: 3
|
|
12613
|
+
},
|
|
12614
|
+
{
|
|
12615
|
+
name: "Function Minimization",
|
|
12616
|
+
subtitle: "Global Optimum",
|
|
12617
|
+
description: "Find the global minimum of a multivariate function with many local minima. Discretize the domain and encode as QUBO. Quantum tunneling helps escape local optima.",
|
|
12618
|
+
asciiDiagram: [
|
|
12619
|
+
"f(x) ^",
|
|
12620
|
+
" | /\\ /\\",
|
|
12621
|
+
" | / \\ / \\",
|
|
12622
|
+
" |/ \\/ \\",
|
|
12623
|
+
" | global \\",
|
|
12624
|
+
" +-----min-----> x"
|
|
12625
|
+
].join("\n"),
|
|
12626
|
+
quboFitStars: 3
|
|
12627
|
+
},
|
|
12628
|
+
{
|
|
12629
|
+
name: "Calibration",
|
|
12630
|
+
subtitle: "Model Fitting",
|
|
12631
|
+
description: "Adjust model parameters to best fit observed data. When the error landscape is non-convex, classical gradient descent gets stuck. QUBO explores the full landscape.",
|
|
12632
|
+
asciiDiagram: [
|
|
12633
|
+
"Data: * * * * * *",
|
|
12634
|
+
"Model: ----\\--/--------",
|
|
12635
|
+
" \\/ <- fit here",
|
|
12636
|
+
"Minimize: sum(error^2)"
|
|
12637
|
+
].join("\n"),
|
|
12638
|
+
quboFitStars: 2
|
|
12639
|
+
}
|
|
12640
|
+
],
|
|
12641
|
+
quboExplainer: "Continuous variables are discretized into binary representation. For N levels, use log2(N) qubits per variable. The continuous objective function is approximated as a polynomial in binary variables, yielding a QUBO. Precision trades off against qubit count.",
|
|
12642
|
+
useCases: [
|
|
12643
|
+
{ industry: "Engineering", application: "Design parameter optimization" },
|
|
12644
|
+
{ industry: "ML/AI", application: "Hyperparameter tuning" },
|
|
12645
|
+
{ industry: "Chemistry", application: "Reaction condition optimization" },
|
|
12646
|
+
{ industry: "Finance", application: "Model calibration" },
|
|
12647
|
+
{ industry: "Manufacturing", application: "Process control tuning" }
|
|
12648
|
+
]
|
|
12649
|
+
}
|
|
12650
|
+
];
|
|
12651
|
+
|
|
11704
12652
|
// ../../b4m-core/packages/services/dist/src/llm/tools/implementation/quantumSchedule/index.js
|
|
11705
12653
|
function formatResult(result) {
|
|
11706
12654
|
const lines = [
|
|
@@ -11925,14 +12873,15 @@ ${problem.description}` : "",
|
|
|
11925
12873
|
"### Machines:",
|
|
11926
12874
|
...problem.machines.map((m) => `- ${m.name} (id: ${m.id})`),
|
|
11927
12875
|
"",
|
|
11928
|
-
|
|
11929
|
-
"```json",
|
|
11930
|
-
JSON.stringify(problem, null, 2),
|
|
11931
|
-
"```",
|
|
11932
|
-
"",
|
|
11933
|
-
"You can now use the `quantum_schedule` tool to solve this problem with various optimization algorithms."
|
|
12876
|
+
'A problem is ready to load. Navigate to the Problem tab and click "Load Problem" to review, tweak, and run solvers.'
|
|
11934
12877
|
];
|
|
11935
|
-
|
|
12878
|
+
const humanReadableSummary = lines.filter((l) => l !== void 0).join("\n");
|
|
12879
|
+
return JSON.stringify({
|
|
12880
|
+
__uiSideEffect: true,
|
|
12881
|
+
type: "populateProblem",
|
|
12882
|
+
payload: problem,
|
|
12883
|
+
displayMessage: humanReadableSummary
|
|
12884
|
+
});
|
|
11936
12885
|
} catch (err) {
|
|
11937
12886
|
return `Error formulating problem: ${err instanceof Error ? err.message : String(err)}`;
|
|
11938
12887
|
}
|
|
@@ -16733,6 +17682,10 @@ var ServerLlmBackend = class {
|
|
|
16733
17682
|
*/
|
|
16734
17683
|
getFallbackModels() {
|
|
16735
17684
|
return [
|
|
17685
|
+
{
|
|
17686
|
+
id: "claude-sonnet-4-6",
|
|
17687
|
+
name: "Claude 4.6 Sonnet"
|
|
17688
|
+
},
|
|
16736
17689
|
{
|
|
16737
17690
|
id: "claude-sonnet-4-5-20250929",
|
|
16738
17691
|
name: "Claude 4.5 Sonnet"
|
|
@@ -16943,6 +17896,7 @@ var WebSocketLlmBackend = class {
|
|
|
16943
17896
|
}
|
|
16944
17897
|
getFallbackModels() {
|
|
16945
17898
|
return [
|
|
17899
|
+
{ id: "claude-sonnet-4-6", name: "Claude 4.6 Sonnet" },
|
|
16946
17900
|
{ id: "claude-sonnet-4-5-20250929", name: "Claude 4.5 Sonnet" },
|
|
16947
17901
|
{ id: "claude-3-5-haiku-20241022", name: "Claude 3.5 Haiku" },
|
|
16948
17902
|
{ id: "gpt-4o", name: "GPT-4o" },
|
|
@@ -17844,6 +18798,7 @@ var MODEL_ALIASES = {
|
|
|
17844
18798
|
"claude-haiku": "claude-3-5-haiku-20241022",
|
|
17845
18799
|
// Version-specific Claude aliases
|
|
17846
18800
|
"claude-4.6-opus": "claude-opus-4-6",
|
|
18801
|
+
"claude-4.6-sonnet": "claude-sonnet-4-6",
|
|
17847
18802
|
"claude-4.5-opus": "claude-opus-4-5-20251101",
|
|
17848
18803
|
"claude-4.5-sonnet": "claude-sonnet-4-5-20250929",
|
|
17849
18804
|
"claude-4.5-haiku": "claude-haiku-4-5-20251001",
|
|
@@ -18605,8 +19560,8 @@ function createBackgroundAgentTools(manager) {
|
|
|
18605
19560
|
case "queued":
|
|
18606
19561
|
return `Agent "${job.agentName}" is queued (waiting for a concurrency slot). Task: ${job.task}`;
|
|
18607
19562
|
case "running": {
|
|
18608
|
-
const
|
|
18609
|
-
return `Agent "${job.agentName}" is still running (${
|
|
19563
|
+
const elapsed2 = Math.round((Date.now() - job.startTime) / 1e3);
|
|
19564
|
+
return `Agent "${job.agentName}" is still running (${elapsed2}s elapsed). Task: ${job.task}`;
|
|
18610
19565
|
}
|
|
18611
19566
|
case "completed": {
|
|
18612
19567
|
const result = manager.getResult(job_id);
|
|
@@ -18638,7 +19593,7 @@ function createBackgroundAgentTools(manager) {
|
|
|
18638
19593
|
const jobs = manager.listJobs();
|
|
18639
19594
|
if (jobs.length === 0) return "No background agents.";
|
|
18640
19595
|
return jobs.map((job) => {
|
|
18641
|
-
const
|
|
19596
|
+
const elapsed2 = Math.round(((job.endTime || Date.now()) - job.startTime) / 1e3);
|
|
18642
19597
|
const statusIcons = {
|
|
18643
19598
|
queued: "\u{1F550}",
|
|
18644
19599
|
running: "\u23F3",
|
|
@@ -18647,7 +19602,7 @@ function createBackgroundAgentTools(manager) {
|
|
|
18647
19602
|
cancelled: "\u{1F6AB}"
|
|
18648
19603
|
};
|
|
18649
19604
|
const statusIcon = statusIcons[job.status] || "\u2753";
|
|
18650
|
-
return `${statusIcon} [${job.id}] ${job.agentName} (${job.status}, ${
|
|
19605
|
+
return `${statusIcon} [${job.id}] ${job.agentName} (${job.status}, ${elapsed2}s) - ${job.task.slice(0, 80)}`;
|
|
18651
19606
|
}).join("\n");
|
|
18652
19607
|
},
|
|
18653
19608
|
toolSchema: {
|