@kortexya/reasoninglayer 1.2.1 → 1.4.0
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/index.cjs +465 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +693 -7
- package/dist/index.d.ts +693 -7
- package/dist/index.js +464 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -7,7 +7,7 @@ var __export = (target, all) => {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// src/config.ts
|
|
10
|
-
var SDK_VERSION = "1.
|
|
10
|
+
var SDK_VERSION = "1.4.0";
|
|
11
11
|
function resolveConfig(config) {
|
|
12
12
|
if (!config.baseUrl) {
|
|
13
13
|
throw new Error("ClientConfig.baseUrl is required");
|
|
@@ -1064,6 +1064,20 @@ var Sorts = class {
|
|
|
1064
1064
|
format: "json",
|
|
1065
1065
|
...params
|
|
1066
1066
|
});
|
|
1067
|
+
/**
|
|
1068
|
+
* No description
|
|
1069
|
+
*
|
|
1070
|
+
* @tags sorts
|
|
1071
|
+
* @name SearchSortsByName
|
|
1072
|
+
* @request GET:/api/v1/sorts/search
|
|
1073
|
+
*/
|
|
1074
|
+
searchSortsByName = (query, params = {}) => this.http.request({
|
|
1075
|
+
path: `/api/v1/sorts/search`,
|
|
1076
|
+
method: "GET",
|
|
1077
|
+
query,
|
|
1078
|
+
format: "json",
|
|
1079
|
+
...params
|
|
1080
|
+
});
|
|
1067
1081
|
/**
|
|
1068
1082
|
* @description Similarity is symmetric: ∼(s₁, s₂) = ∼(s₂, s₁) Degree must be in [0, 1] range.
|
|
1069
1083
|
*
|
|
@@ -1503,6 +1517,24 @@ var Inference = class {
|
|
|
1503
1517
|
format: "json",
|
|
1504
1518
|
...params
|
|
1505
1519
|
});
|
|
1520
|
+
/**
|
|
1521
|
+
* @description Phase 2 v2 entry point for retraction: 1. Removes each term from PG + in-memory stores via [`HomoiconicTermService::remove_term`](osfkb_application::services::HomoiconicTermService::remove_term). 2. When `state.use_plan_engine` is on, submits a single [`DeltaEvent::Retract`](osfkb_application::services::dataflow::DeltaEvent::Retract) to the per-tenant supervisor so the Backward/Forward backward chase decrements every dependent derived fact's `proof_count` (and deletes those whose count reaches zero). Symmetric to [`bulk_add_terms`]; idempotent (term ids absent from the working memory are silently skipped — same shape as [`delete_term`] returning 404, except in the bulk path the missing ids simply don't appear in `removed_term_ids`). Best-effort supervisor enqueue: a supervisor failure does NOT fail the 2xx response — the persist path has succeeded and a future bootstrap can recover any missed retraction. # Mid-batch error handling If `remove_term` fails for a term partway through the batch, the handler **stops accumulating successes**, runs cache invalidation for the prefix that did succeed, submits a single [`DeltaEvent::Retract`](osfkb_application::services::dataflow::DeltaEvent::Retract) covering that prefix, and **then** surfaces the error. This keeps the supervisor and the in-memory caches in sync with the actual store state — a leaked Retract event would orphan derived facts whose only antecedent is now removed, which is a critical correctness violation. # Authorization Requires `X-Tenant-Id` header. The `term_ids` are resolved against that tenant's working memory only — cross-tenant retraction is impossible by construction (the per-tenant `HomoiconicTermService` only sees its own tenant's terms).
|
|
1522
|
+
*
|
|
1523
|
+
* @tags inference
|
|
1524
|
+
* @name BulkRetractTerms
|
|
1525
|
+
* @summary Bulk-retract terms from the working memory.
|
|
1526
|
+
* @request POST:/api/v1/inference/facts/bulk-retract
|
|
1527
|
+
* @secure
|
|
1528
|
+
*/
|
|
1529
|
+
bulkRetractTerms = (data, params = {}) => this.http.request({
|
|
1530
|
+
path: `/api/v1/inference/facts/bulk-retract`,
|
|
1531
|
+
method: "POST",
|
|
1532
|
+
body: data,
|
|
1533
|
+
secure: true,
|
|
1534
|
+
type: "application/json" /* Json */,
|
|
1535
|
+
format: "json",
|
|
1536
|
+
...params
|
|
1537
|
+
});
|
|
1506
1538
|
/**
|
|
1507
1539
|
* @description # DEPRECATED This endpoint is deprecated. Use `DELETE /api/v1/terms/{term_id}` for individual terms. # TRUE HOMOICONIC API # Authorization Requires X-Tenant-Id header.
|
|
1508
1540
|
*
|
|
@@ -7795,6 +7827,34 @@ var Admin = class {
|
|
|
7795
7827
|
format: "json",
|
|
7796
7828
|
...params
|
|
7797
7829
|
});
|
|
7830
|
+
/**
|
|
7831
|
+
* @description Truncates the derived_facts table for the given tenant and queues a BootstrapAll event covering every analyzed rule. Asynchronous: returns the queue depth and current materialization LSN, not the final state. Concurrent rebuilds for the same tenant are rejected with 409 (per-tenant mutex). Full operational runbook (prerequisites, timings, monitoring, failure recovery, known limitations) lives in .claude/SUB_MS_FORWARD_CHAINING_STATUS.md, section 'Operator runbook — derived-facts rebuild'.
|
|
7832
|
+
*
|
|
7833
|
+
* @tags admin
|
|
7834
|
+
* @name RebuildDerivedFacts
|
|
7835
|
+
* @summary Rebuild derived facts for a tenant
|
|
7836
|
+
* @request POST:/api/v1/admin/derived-facts/rebuild/{tenant_id}
|
|
7837
|
+
*/
|
|
7838
|
+
rebuildDerivedFacts = (tenantId, params = {}) => this.http.request({
|
|
7839
|
+
path: `/api/v1/admin/derived-facts/rebuild/${tenantId}`,
|
|
7840
|
+
method: "POST",
|
|
7841
|
+
format: "json",
|
|
7842
|
+
...params
|
|
7843
|
+
});
|
|
7844
|
+
/**
|
|
7845
|
+
* @description Returns event-processing counters (submitted/processed/failed/in-flight), the materialization LSN, the last handler error (if any, truncated to 512 chars), the per-tenant materialization sentinel, the current derived-facts row count, and a racy hint about whether a rebuild is in flight. Intended for operator dashboards; the supervisor itself does not depend on this endpoint.
|
|
7846
|
+
*
|
|
7847
|
+
* @tags admin
|
|
7848
|
+
* @name SupervisorStatus
|
|
7849
|
+
* @summary Get per-tenant supervisor + materialization status
|
|
7850
|
+
* @request GET:/api/v1/admin/derived-facts/status/{tenant_id}
|
|
7851
|
+
*/
|
|
7852
|
+
supervisorStatus = (tenantId, params = {}) => this.http.request({
|
|
7853
|
+
path: `/api/v1/admin/derived-facts/status/${tenantId}`,
|
|
7854
|
+
method: "GET",
|
|
7855
|
+
format: "json",
|
|
7856
|
+
...params
|
|
7857
|
+
});
|
|
7798
7858
|
};
|
|
7799
7859
|
|
|
7800
7860
|
// src/api-spec/generated/ImageExtraction.ts
|
|
@@ -9010,6 +9070,7 @@ var TAGGED_VALUE_TYPES = /* @__PURE__ */ new Set([
|
|
|
9010
9070
|
"Boolean",
|
|
9011
9071
|
"Uninstantiated",
|
|
9012
9072
|
"Reference",
|
|
9073
|
+
"SortId",
|
|
9013
9074
|
"List",
|
|
9014
9075
|
"FuzzyScalar",
|
|
9015
9076
|
"FuzzyNumber",
|
|
@@ -9105,6 +9166,12 @@ function toUntaggedValue(value) {
|
|
|
9105
9166
|
};
|
|
9106
9167
|
}
|
|
9107
9168
|
if (isTaggedValueDto(value)) {
|
|
9169
|
+
if (value.type === "Reference") {
|
|
9170
|
+
return { termId: value.value };
|
|
9171
|
+
}
|
|
9172
|
+
if (value.type === "SortId") {
|
|
9173
|
+
return { sortRef: value.value };
|
|
9174
|
+
}
|
|
9108
9175
|
return value;
|
|
9109
9176
|
}
|
|
9110
9177
|
return value;
|
|
@@ -9517,6 +9584,9 @@ function FeatureInputValueDtoFromFrontToApi(value) {
|
|
|
9517
9584
|
...features ? { features } : {}
|
|
9518
9585
|
};
|
|
9519
9586
|
}
|
|
9587
|
+
if ("sortRef" in value) {
|
|
9588
|
+
return { sort_ref: value.sortRef };
|
|
9589
|
+
}
|
|
9520
9590
|
return { term_id: value.termId };
|
|
9521
9591
|
}
|
|
9522
9592
|
function featuresInputFromFrontToApi(features) {
|
|
@@ -20664,17 +20734,17 @@ function compileLinearExpression(expression, varRefs, nextVar) {
|
|
|
20664
20734
|
const termResults = [];
|
|
20665
20735
|
for (const [varName, coefficient] of Object.entries(expression)) {
|
|
20666
20736
|
if (coefficient === 0) continue;
|
|
20667
|
-
const
|
|
20668
|
-
if (!
|
|
20737
|
+
const varRef2 = varRefs[varName];
|
|
20738
|
+
if (!varRef2) continue;
|
|
20669
20739
|
if (coefficient === 1) {
|
|
20670
|
-
termResults.push(
|
|
20740
|
+
termResults.push(varRef2);
|
|
20671
20741
|
} else {
|
|
20672
20742
|
const resultVar = { name: nextVar() };
|
|
20673
20743
|
antecedents.push({
|
|
20674
20744
|
sortName: "real_times_constraint",
|
|
20675
20745
|
features: {
|
|
20676
20746
|
coefficient: numericTerm(coefficient),
|
|
20677
|
-
variable:
|
|
20747
|
+
variable: varRef2,
|
|
20678
20748
|
result: resultVar
|
|
20679
20749
|
}
|
|
20680
20750
|
});
|
|
@@ -20777,7 +20847,12 @@ var OptimizeClient = class {
|
|
|
20777
20847
|
sorts: [{ name: solutionSortName, parents: ["thing"] }]
|
|
20778
20848
|
});
|
|
20779
20849
|
const sortIdsMap = sortResponse.data.sort_ids;
|
|
20780
|
-
sortId =
|
|
20850
|
+
sortId = sortIdsMap[solutionSortName];
|
|
20851
|
+
if (!sortId) {
|
|
20852
|
+
throw new Error(
|
|
20853
|
+
`bulkCreateSorts did not return an id for '${solutionSortName}' (returned: ${Object.keys(sortIdsMap).join(", ")})`
|
|
20854
|
+
);
|
|
20855
|
+
}
|
|
20781
20856
|
const ruleResponse = await this.inferenceApi.addRule({
|
|
20782
20857
|
term: TermInputDtoFromFrontToApi(compiled.solutionTerm),
|
|
20783
20858
|
antecedents: compiled.antecedents.map(TermInputDtoFromFrontToApi),
|
|
@@ -23156,6 +23231,26 @@ var Value = {
|
|
|
23156
23231
|
reference(id) {
|
|
23157
23232
|
return { type: "Reference", value: id };
|
|
23158
23233
|
},
|
|
23234
|
+
/**
|
|
23235
|
+
* Create a reference to a sort by UUID.
|
|
23236
|
+
*
|
|
23237
|
+
* @param id - The UUID of the sort.
|
|
23238
|
+
* @returns A tagged `SortIdValue`: `{"type": "SortId", "value": "uuid"}`.
|
|
23239
|
+
*
|
|
23240
|
+
* @remarks
|
|
23241
|
+
* Used by homoiconic meta-constraints — primarily `Constraint.typeOf(...)`
|
|
23242
|
+
* — whose feature targets a sort as a first-class value. The chainer
|
|
23243
|
+
* dispatches this directly via `Value::SortId`.
|
|
23244
|
+
*
|
|
23245
|
+
* @example
|
|
23246
|
+
* ```typescript
|
|
23247
|
+
* Value.sortId("550e8400-e29b-41d4-a716-446655440000")
|
|
23248
|
+
* // { type: 'SortId', value: '550e8400-e29b-41d4-a716-446655440000' }
|
|
23249
|
+
* ```
|
|
23250
|
+
*/
|
|
23251
|
+
sortId(id) {
|
|
23252
|
+
return { type: "SortId", value: id };
|
|
23253
|
+
},
|
|
23159
23254
|
/**
|
|
23160
23255
|
* Create a fuzzy scalar with a value and membership degree.
|
|
23161
23256
|
*
|
|
@@ -23573,6 +23668,145 @@ var FuzzyShape = {
|
|
|
23573
23668
|
}
|
|
23574
23669
|
};
|
|
23575
23670
|
|
|
23671
|
+
// src/builders/psi.ts
|
|
23672
|
+
function psi(sortOrName, features) {
|
|
23673
|
+
if (typeof sortOrName === "string") {
|
|
23674
|
+
if (!features) {
|
|
23675
|
+
return { __psiTerm: true, sortName: sortOrName };
|
|
23676
|
+
}
|
|
23677
|
+
return {
|
|
23678
|
+
__psiTerm: true,
|
|
23679
|
+
sortName: sortOrName,
|
|
23680
|
+
features
|
|
23681
|
+
};
|
|
23682
|
+
}
|
|
23683
|
+
if (!features) {
|
|
23684
|
+
return { __psiTerm: true, sortId: sortOrName.sortId };
|
|
23685
|
+
}
|
|
23686
|
+
return {
|
|
23687
|
+
__psiTerm: true,
|
|
23688
|
+
sortId: sortOrName.sortId,
|
|
23689
|
+
features
|
|
23690
|
+
};
|
|
23691
|
+
}
|
|
23692
|
+
function constrained(name, constraint) {
|
|
23693
|
+
return { __constrainedVar: true, name, constraint };
|
|
23694
|
+
}
|
|
23695
|
+
|
|
23696
|
+
// src/builders/constraint.ts
|
|
23697
|
+
var ARITHMETIC_SORT = {
|
|
23698
|
+
"+": "plus_constraint",
|
|
23699
|
+
"-": "minus_constraint",
|
|
23700
|
+
"*": "times_constraint",
|
|
23701
|
+
"/": "div_constraint"
|
|
23702
|
+
};
|
|
23703
|
+
var Constraint = {
|
|
23704
|
+
/**
|
|
23705
|
+
* State that a variable is a term of a given sort. The chainer enumerates
|
|
23706
|
+
* every persisted term of that sort via backtracking.
|
|
23707
|
+
*
|
|
23708
|
+
* @param variable - Variable name (e.g. `'?E'`) or pre-built variable Ψ-term.
|
|
23709
|
+
* @param sortUuid - UUID of the target sort (resolve from
|
|
23710
|
+
* `client.inference.getMetaSorts()` or your own `createSort` response).
|
|
23711
|
+
* @returns A `sort_constraint` term.
|
|
23712
|
+
*/
|
|
23713
|
+
typeOf(variable, sortUuid) {
|
|
23714
|
+
return psi("sort_constraint", {
|
|
23715
|
+
var: variable,
|
|
23716
|
+
sort: { sortRef: sortUuid }
|
|
23717
|
+
});
|
|
23718
|
+
},
|
|
23719
|
+
/**
|
|
23720
|
+
* State that a variable's feature equals a target. The chainer unifies
|
|
23721
|
+
* the variable's feature value with the target.
|
|
23722
|
+
*
|
|
23723
|
+
* **Important**: the chainer's `feature_constraint` only unifies
|
|
23724
|
+
* term-references with term-references. The variable's feature on the
|
|
23725
|
+
* persisted side must itself be a `Value::Reference`. Comparing against
|
|
23726
|
+
* literals (e.g. `has('?N', 'name', 'S')` where `name` is stored as a
|
|
23727
|
+
* plain string) silently returns zero solutions — that's a chainer
|
|
23728
|
+
* design constraint, not a builder bug.
|
|
23729
|
+
*
|
|
23730
|
+
* @param variable - The owning variable (e.g. `'?Edge'`).
|
|
23731
|
+
* @param feature - The feature name (e.g. `'src'`).
|
|
23732
|
+
* @param target - The target — typically another variable (`'?Src'`)
|
|
23733
|
+
* or an existing term referenced by its UUID via `'!<uuid>'`.
|
|
23734
|
+
* @returns A `feature_constraint` term.
|
|
23735
|
+
*/
|
|
23736
|
+
has(variable, feature, target) {
|
|
23737
|
+
return psi("feature_constraint", {
|
|
23738
|
+
var: variable,
|
|
23739
|
+
feature,
|
|
23740
|
+
target
|
|
23741
|
+
});
|
|
23742
|
+
},
|
|
23743
|
+
/**
|
|
23744
|
+
* State a boolean comparison between two operands. The chainer
|
|
23745
|
+
* residuates the constraint until both sides are bound; when they are,
|
|
23746
|
+
* the comparison must hold or the proof branch fails.
|
|
23747
|
+
*
|
|
23748
|
+
* @param left - Left operand — variable, literal number, or term ref.
|
|
23749
|
+
* @param op - Comparison operator.
|
|
23750
|
+
* @param right - Right operand.
|
|
23751
|
+
* @returns A `guard_constraint` term.
|
|
23752
|
+
*/
|
|
23753
|
+
where(left, op, right) {
|
|
23754
|
+
return psi("guard_constraint", {
|
|
23755
|
+
left,
|
|
23756
|
+
operator: op,
|
|
23757
|
+
right
|
|
23758
|
+
});
|
|
23759
|
+
},
|
|
23760
|
+
/**
|
|
23761
|
+
* State that `result = left op right`. Selects the chainer sort by op:
|
|
23762
|
+
* `+` → `plus_constraint`, `-` → `minus_constraint`, `*` →
|
|
23763
|
+
* `times_constraint`, `/` → `div_constraint`. The chainer reads each
|
|
23764
|
+
* operand as either a Reference variable or a numeric literal, and can
|
|
23765
|
+
* run forward, reverse, or verify depending on which operands are
|
|
23766
|
+
* bound.
|
|
23767
|
+
*
|
|
23768
|
+
* @param result - Result variable or value (`z`).
|
|
23769
|
+
* @param op - Arithmetic operator.
|
|
23770
|
+
* @param left - Left operand (`x`).
|
|
23771
|
+
* @param right - Right operand (`y`).
|
|
23772
|
+
* @returns The appropriate arithmetic-constraint term.
|
|
23773
|
+
*/
|
|
23774
|
+
equation(result, op, left, right) {
|
|
23775
|
+
return psi(ARITHMETIC_SORT[op], { x: left, y: right, z: result });
|
|
23776
|
+
},
|
|
23777
|
+
/**
|
|
23778
|
+
* Constrain a variable to be an integer in the inclusive range
|
|
23779
|
+
* `[min, max]`. Required before the chainer's labeling step can assign
|
|
23780
|
+
* a concrete value via {@link Constraint.solveFor}.
|
|
23781
|
+
*
|
|
23782
|
+
* @param variable - Variable name to constrain.
|
|
23783
|
+
* @param min - Lower bound (inclusive).
|
|
23784
|
+
* @param max - Upper bound (inclusive).
|
|
23785
|
+
* @returns An `fd_domain_constraint` term.
|
|
23786
|
+
*/
|
|
23787
|
+
intRange(variable, min, max) {
|
|
23788
|
+
return psi("fd_domain_constraint", {
|
|
23789
|
+
var: variable,
|
|
23790
|
+
min,
|
|
23791
|
+
max
|
|
23792
|
+
});
|
|
23793
|
+
},
|
|
23794
|
+
/**
|
|
23795
|
+
* Search for concrete integer assignments to the listed variables that
|
|
23796
|
+
* satisfy every other constraint mentioning them. Place this at the END
|
|
23797
|
+
* of a clause body — it's the labeling/search step that turns a
|
|
23798
|
+
* constraint network into solutions.
|
|
23799
|
+
*
|
|
23800
|
+
* @param variables - Variable names to assign.
|
|
23801
|
+
* @returns An `fd_labeling_constraint` term.
|
|
23802
|
+
*/
|
|
23803
|
+
solveFor(...variables) {
|
|
23804
|
+
return psi("fd_labeling_constraint", {
|
|
23805
|
+
vars: variables
|
|
23806
|
+
});
|
|
23807
|
+
}
|
|
23808
|
+
};
|
|
23809
|
+
|
|
23576
23810
|
// src/builders/guard.ts
|
|
23577
23811
|
function guard(op, right) {
|
|
23578
23812
|
return {
|
|
@@ -23750,31 +23984,6 @@ var SortBuilder = class _SortBuilder {
|
|
|
23750
23984
|
}
|
|
23751
23985
|
};
|
|
23752
23986
|
|
|
23753
|
-
// src/builders/psi.ts
|
|
23754
|
-
function psi(sortOrName, features) {
|
|
23755
|
-
if (typeof sortOrName === "string") {
|
|
23756
|
-
if (!features) {
|
|
23757
|
-
return { __psiTerm: true, sortName: sortOrName };
|
|
23758
|
-
}
|
|
23759
|
-
return {
|
|
23760
|
-
__psiTerm: true,
|
|
23761
|
-
sortName: sortOrName,
|
|
23762
|
-
features
|
|
23763
|
-
};
|
|
23764
|
-
}
|
|
23765
|
-
if (!features) {
|
|
23766
|
-
return { __psiTerm: true, sortId: sortOrName.sortId };
|
|
23767
|
-
}
|
|
23768
|
-
return {
|
|
23769
|
-
__psiTerm: true,
|
|
23770
|
-
sortId: sortOrName.sortId,
|
|
23771
|
-
features
|
|
23772
|
-
};
|
|
23773
|
-
}
|
|
23774
|
-
function constrained(name, constraint) {
|
|
23775
|
-
return { __constrainedVar: true, name, constraint };
|
|
23776
|
-
}
|
|
23777
|
-
|
|
23778
23987
|
// src/builders/allen.ts
|
|
23779
23988
|
function allen(relation, intervalA, intervalBTermId) {
|
|
23780
23989
|
return {
|
|
@@ -23785,6 +23994,229 @@ function allen(relation, intervalA, intervalBTermId) {
|
|
|
23785
23994
|
};
|
|
23786
23995
|
}
|
|
23787
23996
|
|
|
23997
|
+
// src/builders/flow.ts
|
|
23998
|
+
function nodeVar(name) {
|
|
23999
|
+
const sanitized = name.replace(/[^A-Za-z0-9_]/g, "_");
|
|
24000
|
+
return { name: `?N_${sanitized}` };
|
|
24001
|
+
}
|
|
24002
|
+
function varRef(name) {
|
|
24003
|
+
return { name };
|
|
24004
|
+
}
|
|
24005
|
+
function freshVar(prefix, counter) {
|
|
24006
|
+
const name = `?${prefix}${counter.n}`;
|
|
24007
|
+
counter.n += 1;
|
|
24008
|
+
return name;
|
|
24009
|
+
}
|
|
24010
|
+
function normaliseEdge(e) {
|
|
24011
|
+
if (Array.isArray(e)) {
|
|
24012
|
+
const [from, to, cap, options] = e;
|
|
24013
|
+
return { from, to, cap, ...options ?? {} };
|
|
24014
|
+
}
|
|
24015
|
+
return e;
|
|
24016
|
+
}
|
|
24017
|
+
function buildEdges(edges, counter) {
|
|
24018
|
+
const edgeTerms = [];
|
|
24019
|
+
const edgeFlows = [];
|
|
24020
|
+
for (const raw of edges) {
|
|
24021
|
+
const e = normaliseEdge(raw);
|
|
24022
|
+
const flowVar = e.flow ?? freshVar("F", counter);
|
|
24023
|
+
edgeFlows.push({ from: e.from, to: e.to, var: flowVar });
|
|
24024
|
+
const features = {
|
|
24025
|
+
src: nodeVar(e.from),
|
|
24026
|
+
dst: nodeVar(e.to),
|
|
24027
|
+
cap: e.cap,
|
|
24028
|
+
flow: varRef(flowVar)
|
|
24029
|
+
};
|
|
24030
|
+
if (e.cost != null) features.cost = e.cost;
|
|
24031
|
+
if (e.label != null) features.label = e.label;
|
|
24032
|
+
edgeTerms.push(psi("flow_edge_constraint", features));
|
|
24033
|
+
}
|
|
24034
|
+
return { edgeTerms, edgeFlows };
|
|
24035
|
+
}
|
|
24036
|
+
function solveTerm(source, sink) {
|
|
24037
|
+
return psi("flow_solve_constraint", {
|
|
24038
|
+
source: nodeVar(source),
|
|
24039
|
+
sink: nodeVar(sink)
|
|
24040
|
+
});
|
|
24041
|
+
}
|
|
24042
|
+
var Flow = {
|
|
24043
|
+
/**
|
|
24044
|
+
* Build a max-flow problem.
|
|
24045
|
+
*
|
|
24046
|
+
* Emits one `flow_edge_constraint` per edge, one
|
|
24047
|
+
* `flow_max_constraint` with the requested output binding, and a
|
|
24048
|
+
* `flow_solve_constraint` trigger. Returns the constraint terms
|
|
24049
|
+
* plus the names of every output variable.
|
|
24050
|
+
*/
|
|
24051
|
+
maxFlow(input) {
|
|
24052
|
+
const counter = { n: 0 };
|
|
24053
|
+
const { edgeTerms, edgeFlows } = buildEdges(input.edges, counter);
|
|
24054
|
+
const flowValue = input.flowValue ?? freshVar("V_flow", counter);
|
|
24055
|
+
const constraints = [
|
|
24056
|
+
...edgeTerms,
|
|
24057
|
+
psi("flow_max_constraint", {
|
|
24058
|
+
source: nodeVar(input.source),
|
|
24059
|
+
sink: nodeVar(input.sink),
|
|
24060
|
+
flow_value: varRef(flowValue)
|
|
24061
|
+
}),
|
|
24062
|
+
solveTerm(input.source, input.sink)
|
|
24063
|
+
];
|
|
24064
|
+
return { constraints, vars: { flowValue, edgeFlows } };
|
|
24065
|
+
},
|
|
24066
|
+
/**
|
|
24067
|
+
* Build a min-cut problem.
|
|
24068
|
+
*
|
|
24069
|
+
* Emits `flow_min_cut_constraint` and binds `cut_value`,
|
|
24070
|
+
* `cut_edges`, `source_side`, `sink_side` to the requested
|
|
24071
|
+
* variable names (auto-generated when omitted).
|
|
24072
|
+
*/
|
|
24073
|
+
minCut(input) {
|
|
24074
|
+
const counter = { n: 0 };
|
|
24075
|
+
const { edgeTerms, edgeFlows } = buildEdges(input.edges, counter);
|
|
24076
|
+
const cutValue = input.cutValue ?? freshVar("CutValue", counter);
|
|
24077
|
+
const cutEdges = input.cutEdges ?? freshVar("CutEdges", counter);
|
|
24078
|
+
const sourceSide = input.sourceSide ?? freshVar("SrcSide", counter);
|
|
24079
|
+
const sinkSide = input.sinkSide ?? freshVar("SnkSide", counter);
|
|
24080
|
+
const constraints = [
|
|
24081
|
+
...edgeTerms,
|
|
24082
|
+
psi("flow_min_cut_constraint", {
|
|
24083
|
+
source: nodeVar(input.source),
|
|
24084
|
+
sink: nodeVar(input.sink),
|
|
24085
|
+
cut_value: varRef(cutValue),
|
|
24086
|
+
cut_edges: varRef(cutEdges),
|
|
24087
|
+
source_side: varRef(sourceSide),
|
|
24088
|
+
sink_side: varRef(sinkSide)
|
|
24089
|
+
}),
|
|
24090
|
+
solveTerm(input.source, input.sink)
|
|
24091
|
+
];
|
|
24092
|
+
return {
|
|
24093
|
+
constraints,
|
|
24094
|
+
vars: { cutValue, cutEdges, sourceSide, sinkSide, edgeFlows }
|
|
24095
|
+
};
|
|
24096
|
+
},
|
|
24097
|
+
/**
|
|
24098
|
+
* Build a min-cost-max-flow problem. Per-edge `cost` is required
|
|
24099
|
+
* for the optimisation to be meaningful (defaults to 0 if absent).
|
|
24100
|
+
*/
|
|
24101
|
+
minCostMaxFlow(input) {
|
|
24102
|
+
const counter = { n: 0 };
|
|
24103
|
+
const { edgeTerms, edgeFlows } = buildEdges(input.edges, counter);
|
|
24104
|
+
const flowValue = input.flowValue ?? freshVar("V_flow", counter);
|
|
24105
|
+
const totalCost = input.totalCost ?? freshVar("Cost", counter);
|
|
24106
|
+
const constraints = [
|
|
24107
|
+
...edgeTerms,
|
|
24108
|
+
psi("flow_min_cost_max_flow_constraint", {
|
|
24109
|
+
source: nodeVar(input.source),
|
|
24110
|
+
sink: nodeVar(input.sink),
|
|
24111
|
+
flow_value: varRef(flowValue),
|
|
24112
|
+
total_cost: varRef(totalCost)
|
|
24113
|
+
}),
|
|
24114
|
+
solveTerm(input.source, input.sink)
|
|
24115
|
+
];
|
|
24116
|
+
return { constraints, vars: { flowValue, totalCost, edgeFlows } };
|
|
24117
|
+
},
|
|
24118
|
+
/**
|
|
24119
|
+
* Build a Dulmage-Mendelsohn edge-classification problem.
|
|
24120
|
+
*
|
|
24121
|
+
* Each edge is classified as `"always"`, `"never"`, or
|
|
24122
|
+
* `"sometimes"` used across the space of all max flows (or all
|
|
24123
|
+
* min-cost max flows when `optimal: true`).
|
|
24124
|
+
*/
|
|
24125
|
+
classifyEdges(input) {
|
|
24126
|
+
const counter = { n: 0 };
|
|
24127
|
+
const { edgeTerms, edgeFlows } = buildEdges(input.edges, counter);
|
|
24128
|
+
const classifications = input.classifications ?? freshVar("Classes", counter);
|
|
24129
|
+
const objectiveFeatures = {
|
|
24130
|
+
source: nodeVar(input.source),
|
|
24131
|
+
sink: nodeVar(input.sink),
|
|
24132
|
+
classifications: varRef(classifications)
|
|
24133
|
+
};
|
|
24134
|
+
if (input.optimal) objectiveFeatures.optimal = true;
|
|
24135
|
+
const constraints = [
|
|
24136
|
+
...edgeTerms,
|
|
24137
|
+
psi("flow_classify_edges_constraint", objectiveFeatures),
|
|
24138
|
+
solveTerm(input.source, input.sink)
|
|
24139
|
+
];
|
|
24140
|
+
return { constraints, vars: { classifications, edgeFlows } };
|
|
24141
|
+
},
|
|
24142
|
+
/** Low-level: build a single `flow_edge_constraint` psi-term. */
|
|
24143
|
+
edge(from, to, cap, options = {}) {
|
|
24144
|
+
const features = {
|
|
24145
|
+
src: nodeVar(from),
|
|
24146
|
+
dst: nodeVar(to),
|
|
24147
|
+
cap
|
|
24148
|
+
};
|
|
24149
|
+
if (options.flow) features.flow = varRef(options.flow);
|
|
24150
|
+
if (options.cost != null) features.cost = options.cost;
|
|
24151
|
+
if (options.label != null) features.label = options.label;
|
|
24152
|
+
return psi("flow_edge_constraint", features);
|
|
24153
|
+
},
|
|
24154
|
+
/** Low-level: build a single `flow_solve_constraint` psi-term. */
|
|
24155
|
+
solve(source, sink) {
|
|
24156
|
+
return solveTerm(source, sink);
|
|
24157
|
+
},
|
|
24158
|
+
/**
|
|
24159
|
+
* Low-level: build a single `flow_max_constraint` psi-term.
|
|
24160
|
+
*
|
|
24161
|
+
* @example
|
|
24162
|
+
* ```typescript
|
|
24163
|
+
* const constraints = [
|
|
24164
|
+
* Flow.edge('s', 'a', 10),
|
|
24165
|
+
* Flow.edge('a', 't', 10),
|
|
24166
|
+
* Flow.maxObjective({ source: 's', sink: 't', flowValue: '?V' }),
|
|
24167
|
+
* Flow.solve('s', 't'),
|
|
24168
|
+
* ];
|
|
24169
|
+
* ```
|
|
24170
|
+
*/
|
|
24171
|
+
maxObjective(opts) {
|
|
24172
|
+
return psi("flow_max_constraint", {
|
|
24173
|
+
source: nodeVar(opts.source),
|
|
24174
|
+
sink: nodeVar(opts.sink),
|
|
24175
|
+
flow_value: varRef(opts.flowValue)
|
|
24176
|
+
});
|
|
24177
|
+
},
|
|
24178
|
+
/** Low-level: build a single `flow_min_cut_constraint` psi-term. */
|
|
24179
|
+
minCutObjective(opts) {
|
|
24180
|
+
return psi("flow_min_cut_constraint", {
|
|
24181
|
+
source: nodeVar(opts.source),
|
|
24182
|
+
sink: nodeVar(opts.sink),
|
|
24183
|
+
cut_value: varRef(opts.cutValue),
|
|
24184
|
+
cut_edges: varRef(opts.cutEdges),
|
|
24185
|
+
source_side: varRef(opts.sourceSide),
|
|
24186
|
+
sink_side: varRef(opts.sinkSide)
|
|
24187
|
+
});
|
|
24188
|
+
},
|
|
24189
|
+
/** Low-level: build a single `flow_min_cost_max_flow_constraint` psi-term. */
|
|
24190
|
+
minCostMaxFlowObjective(opts) {
|
|
24191
|
+
return psi("flow_min_cost_max_flow_constraint", {
|
|
24192
|
+
source: nodeVar(opts.source),
|
|
24193
|
+
sink: nodeVar(opts.sink),
|
|
24194
|
+
flow_value: varRef(opts.flowValue),
|
|
24195
|
+
total_cost: varRef(opts.totalCost)
|
|
24196
|
+
});
|
|
24197
|
+
},
|
|
24198
|
+
/** Low-level: build a single `flow_classify_edges_constraint` psi-term. */
|
|
24199
|
+
classifyEdgesObjective(opts) {
|
|
24200
|
+
const features = {
|
|
24201
|
+
source: nodeVar(opts.source),
|
|
24202
|
+
sink: nodeVar(opts.sink),
|
|
24203
|
+
classifications: varRef(opts.classifications)
|
|
24204
|
+
};
|
|
24205
|
+
if (opts.optimal) features.optimal = true;
|
|
24206
|
+
return psi("flow_classify_edges_constraint", features);
|
|
24207
|
+
},
|
|
24208
|
+
/**
|
|
24209
|
+
* Low-level: get the node-variable reference used to identify a
|
|
24210
|
+
* node name in goals built by this builder. Exposed so callers
|
|
24211
|
+
* composing constraints by hand can refer to the same logical node
|
|
24212
|
+
* the high-level helpers would produce — e.g., to add a feature
|
|
24213
|
+
* test on the same node term inside the same goal.
|
|
24214
|
+
*/
|
|
24215
|
+
node(name) {
|
|
24216
|
+
return nodeVar(name);
|
|
24217
|
+
}
|
|
24218
|
+
};
|
|
24219
|
+
|
|
23788
24220
|
// src/utils/discrimination.ts
|
|
23789
24221
|
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
23790
24222
|
function isUuid(s) {
|
|
@@ -23824,6 +24256,7 @@ exports.Cognitive = cognitive_exports;
|
|
|
23824
24256
|
exports.Collections = collections_exports;
|
|
23825
24257
|
exports.Communities = communities_exports;
|
|
23826
24258
|
exports.Compliance = compliance_exports;
|
|
24259
|
+
exports.Constraint = Constraint;
|
|
23827
24260
|
exports.ConstraintViolationError = ConstraintViolationError;
|
|
23828
24261
|
exports.Constraints = constraints_exports;
|
|
23829
24262
|
exports.Control = control_exports;
|
|
@@ -23831,6 +24264,7 @@ exports.Conversation = conversation_exports;
|
|
|
23831
24264
|
exports.Discovery = discovery_exports;
|
|
23832
24265
|
exports.Execution = execution_exports;
|
|
23833
24266
|
exports.Extract = extract_exports;
|
|
24267
|
+
exports.Flow = Flow;
|
|
23834
24268
|
exports.FlowNetworks = flow_networks_exports;
|
|
23835
24269
|
exports.ForbiddenError = ForbiddenError;
|
|
23836
24270
|
exports.Functions = functions_exports;
|