Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/solverforge-macros/WIREFRAME.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ runtime scalar surface is candidate-index based.
- Hidden scalar metadata bridge: private indexed helpers for scalar variable count, name, allows-unassigned, value-source metadata, getter/setter, and entity-local value slices. Helper order matches `entity_descriptor()` genuine scalar variable order; the index is used for generated getter/setter dispatch, while manifest hook attachment resolves descriptor variables by descriptor index plus variable name.
- Hidden list metadata bridge (when the entity has a `#[planning_list_variable]` field): public cross-module `__SOLVERFORGE_LIST_VARIABLE_COUNT` plus private `__SOLVERFORGE_LIST_VARIABLE_NAME`, `__SOLVERFORGE_LIST_ELEMENT_COLLECTION`, `__solverforge_list_field()`, `__solverforge_list_field_mut()`, `__solverforge_list_metadata()`
- Hidden list metadata bridge implementation (when the entity has a `#[planning_list_variable]` field): `impl __internal::ListVariableEntity<Solution> for Entity`
- Hidden unassigned bridge (when the entity has exactly one `Option<_>` planning variable): `impl __internal::UnassignedEntity<Solution> for Entity`, enabling `.unassigned()` on `UniConstraintStream<_, Entity, ...>` without a generated public trait import
- Unassigned bridge (when the entity has exactly one `Option<_>` planning variable): `impl __internal::UnassignedEntity<Solution> for Entity`, the public `stream::UnassignedEntity`, enabling `.unassigned()` on `UniConstraintStream<_, Entity, ...>` without a generated public trait import

### Planning Solution Support Derive

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ help: the trait `SingleConstraint` is not implemented for `Count`
IncrementalUniConstraint<S, A, E, F, W, Sc>
ListPrecedenceMakespanConstraint<S>
OperatorTerminal<S, O, W, Sc>
SharedOperatorTerminal<S, O, A, solverforge::constraint::relational::OperatorScorer<W, Sc>, Sc>
SharedOperatorTerminal<S, O, A, OperatorScorer<W, Sc>, Sc>
Uni<S, Out, Src, F, W, Sc>
solverforge::constraint::projected::Bi<S, Out, K, Src, F, KF, PF, W, Sc>
solverforge::constraint::projected::DirectedBi<S, Out, K, Src, F, KL, KR, PF, W, Sc>
Expand Down
31 changes: 25 additions & 6 deletions crates/solverforge-scoring/WIREFRAME.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ migration of the fluent stream families:
- `constraint::relational::OperatorTerminal<S, O, W, Sc>::new(constraint_ref,
impact, operator, weight, hard)` scores a generic operator; its weight takes
`(&S, &O::View<'a>)`. It implements incremental scoring, reset, full counts,
and cold explanations. `ExplainRow` is a hidden analysis bridge.
and cold explanations. `ExplainRow::explain(&self, entities)` appends the
entities a row view was built from; terminals call it only on the cold
explanation path, and a custom operator implements it for its `View` to make
its matches explainable.
- `stream::joiner::plan::{CompileCondition, IndexedPlan, ExecutablePlan}`
separates condition compilation, owned index state, and borrowed-row execution.
Candidate probes return `Cow<'i, [RowHandle]>`: equality borrows an exact
Expand Down Expand Up @@ -204,7 +207,8 @@ src/
│ ├── relational/
│ │ ├── mod.rs — Module declarations and selected re-exports
│ │ ├── operator_terminal.rs — OperatorTerminal<S,O,W,Sc> over one generic operator
│ │ ├── operator_scorer.rs — OperatorScorer, OperatorScorerSet, ScorerChain, and RowWeight/AdaptWeight adapters
│ │ ├── operator_scorer.rs — OperatorScorer, ScorerChain, and RowWeight/AdaptWeight adapters
│ │ ├── operator_scorer/set.rs — OperatorScorerSet, the scorer-set contract shared terminals score through
│ │ ├── shared_terminal.rs — SharedOperatorTerminal/Builder and chained terminal sharing
│ │ └── grouped_weights.rs — Group/direct-complement/optional-complement weight adapters
│ ├── projected.rs — Projected retained scoring-row constraint module root and re-exports
Expand Down Expand Up @@ -305,7 +309,7 @@ src/
│ ├── projected_stream/source/merged.rs — Merged projected sources with source-slot offsets
│ ├── projected_stream/source/joined.rs — Cross-join `.project(...)` projected source
│ ├── collection_extract.rs — CollectionExtract trait, hidden source metadata and FilteredExtract membership adapter, source() constructor
│ ├── unassigned.rs — Hidden UnassignedEntity hook and `.unassigned()` stream method
│ ├── unassigned.rs — UnassignedEntity and the `.unassigned()` stream method
│ ├── weighting_support.rs — ConstraintWeight, FixedWeight, HardWeight, and dynamic closure-weight adapters
│ ├── join_target.rs — JoinTarget/ToViewPlan dispatch for self-join, keyed cross-join, comparison, overlap, composed, and predicate cross-join
│ ├── key_extract.rs — KeyExtract trait, EntityKeyAdapter struct
Expand Down Expand Up @@ -752,8 +756,10 @@ Dynamic closure weights are non-hard metadata by default, even when their score
- `new()`, `for_each()` → `UniConstraintStream`
- Generated solution source methods pass `for_each()` hidden descriptor/static source metadata.

**`UnassignedEntity<S>`** — `fn is_unassigned(solution: &S, entity: &Self) -> bool`; enables `UniConstraintStream::unassigned()`. `#[planning_entity]` implements it for an entity with exactly one `Option<_>` planning variable (unassigned while `None`); implement it by hand for any other notion of unassigned.

**`UniConstraintStream<S, A, E, F, Sc>`** — Single collection stream.
- Operations: `filter()`, `unassigned()` when the entity implements hidden `UnassignedEntity<S>`, `join(target)` (single dispatch via `JoinTarget`), `group_by()`, `balance()`, `project(projection)` → `stream::projected::Stream`, `flattened(flatten)` → `FlattenedCollectionTarget`, `if_exists(target)`, `if_not_exists(target)`, `penalize(weight_or_fn)`, `reward(weight_or_fn)`
- Operations: `filter()`, `unassigned()` when the entity implements `UnassignedEntity<S>`, `join(target)` (single dispatch via `JoinTarget`), `group_by()`, `balance()`, `project(projection)` → `stream::projected::Stream`, `flattened(flatten)` → `FlattenedCollectionTarget`, `if_exists(target)`, `if_not_exists(target)`, `penalize(weight_or_fn)`, `reward(weight_or_fn)`
- `UniConstraintStream` implements `CollectionExtract` by delegating extraction to its source and applying its accumulated filter through `contains(...)`.
- Stream targets preserve their own source filters when passed to keyed or predicate cross-joins. This lets `.join((ConstraintFactory::new().for_each(source).filter(pred), equal_bi(...)))` keep the right-side source predicate inside the joined stream.
- For the first unary keyed equality cross-join, the left unary filter is preserved through hidden source membership before key extraction and pair creation. Original source indexes and change metadata remain intact across incremental membership transitions. Post-join filters remain joined-row filters. This left-filter pushdown does not apply to comparison, overlap, composed-condition, predicate, or same-source self-join dispatch.
Expand Down Expand Up @@ -789,8 +795,21 @@ callers obtain these opaque carriers through fluent operations and continue on

**`stream::projected::DirectedBiBuilder`** — `named()` → `constraint::projected::DirectedBi`

**`RowCoordinate`** — Hidden support coordinate for projected rows:
`{ primary_owner, secondary_owner, emit_index }`. `primary_owner` is always
**`stream::projected::Source<S, Out>`** — The producer behind a projected
stream: `type State`, `const MAX_EMITS`, `source_count()`, `change_source(slot)`,
`build_state(solution)`, `collect_all(solution, state, visit)`,
`collect_entity(solution, state, slot, entity_index, visit)`, and
`insert_entity_state`/`retract_entity_state`. Single-source projections,
filters, merges and joined pairs implement it; the fluent `project`, `filter`,
`merge` and `join` methods build them.

**`RowOwner`** — `{ source_slot, entity_index }`: one entity a projected row
derives from.

**`RowCoordinate`** — The stable identity of a projected row:
`{ primary_owner, secondary_owner, emit_index }`, built with `single(...)` or
`pair(...)`, visited with `for_each_owner(...)`, shifted with
`offset_source_slots(offset)`. `primary_owner` is always
present; `secondary_owner` is present for joined-pair rows from
`stream::cross::Bi::project(...)`. It is used to keep projected self-join
orientation stable across sparse row-slot reuse and to dedupe callbacks when
Expand Down
Loading
Loading