Skip to content

perf(constraint-streams): implement runtime node deactivation#2337

Merged
triceo merged 26 commits into
TimefoldAI:mainfrom
triceo:unlinking
Jun 9, 2026
Merged

perf(constraint-streams): implement runtime node deactivation#2337
triceo merged 26 commits into
TimefoldAI:mainfrom
triceo:unlinking

Conversation

@triceo

@triceo triceo commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator

While I was there, I moved the hidden network visualization feature to Enterprise, and exposed it publicly as part of constraint profiling.

Enterprise counterpart: https://github.com/TimefoldAI/timefold-solver-enterprise/pull/662

Copilot AI review requested due to automatic review settings June 7, 2026 07:03
@triceo triceo requested a review from TomCools as a code owner June 7, 2026 07:03
@triceo triceo self-assigned this Jun 7, 2026
@triceo triceo added this to the v2.3.0 milestone Jun 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces runtime node deactivation to Bavet-based Constraint Streams (and related node networks), allowing the engine to identify and skip propagating through nodes that provably cannot produce any tuples for a given working solution, improving performance while keeping behavior safe.

Changes:

  • Added an ActivitySupport initialization/activation protocol and implemented activity propagation across tuple lifecycles and nodes.
  • Reworked node network/session infrastructure (AbstractBavetNodeNetwork, ConstraintStreamsBavetNodeNetwork, etc.) to trim inactive propagators after initialization.
  • Added focused unit tests and documentation describing runtime deactivation behavior; removed the old node-network visualization implementation.

Reviewed changes

Copilot reviewed 62 out of 62 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
docs/src/modules/ROOT/pages/constraints-and-score/performance.adoc Documents runtime constraint deactivation when constraints are provably irrelevant.
core/src/test/java/ai/timefold/solver/core/impl/bavet/uni/IfExistsUniNodeActivityTest.java Verifies activation rules for ifExists/ifNotExists nodes.
core/src/test/java/ai/timefold/solver/core/impl/bavet/uni/ForEachUniNodeActivityTest.java Verifies ForEach node activation behavior based on inserted facts and downstream activity.
core/src/test/java/ai/timefold/solver/core/impl/bavet/uni/ConcatUniUniNodeActivityTest.java Verifies concat activation semantics when one/both sides are empty.
core/src/test/java/ai/timefold/solver/core/impl/bavet/common/SingleInputNodeActivityTest.java Verifies default single-input activation forwarding/behavior.
core/src/test/java/ai/timefold/solver/core/impl/bavet/bi/JoinBiNodeActivityTest.java Verifies join deactivation when either side cannot produce tuples.
core/src/test/java/ai/timefold/solver/core/impl/bavet/BavetNodeDeactivationTest.java End-to-end tests asserting chains deactivate/activate based on solution contents.
core/src/test/java/ai/timefold/solver/core/api/solver/SolutionManagerTest.java Removes tests for node-network visualization API that was removed.
core/src/main/java/module-info.java Exports additional internal packages to the enterprise module.
core/src/main/java/ai/timefold/solver/core/impl/solver/DefaultSolutionManager.java Removes node-network visualization method and related dependencies.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetForEachUniConstraintStream.java Adjusts generic handling and simplifies equals implementation.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/ConstraintStreamsBavetNodeNetwork.java Adds node-network implementation that can log deactivated constraints post-initialization.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/Scorer.java Makes scorer implement activity so constraints can be marked inactive when upstream can’t produce.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/ConstraintNodeBuildHelper.java Tracks scorers/profile IDs and builds ConstraintStreamsBavetNodeNetwork.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/common/BavetPrecomputeBuildHelper.java Migrates precompute to the new node-network abstraction.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintSessionFactory.java Builds the new constraint-streams node network and integrates profiling registration.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintSession.java Uses the new node network type and forwards profiling summarization.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraintFactory.java Updates javadoc references after session factory signature change.
core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/BavetConstraintStreamScoreDirectorFactory.java Removes visualization consumer plumbing from session creation.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/enumerating/uni/AbstractForEachEnumeratingStream.java Updates imports due to root node type rename/refactor.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/enumerating/DatasetSessionFactory.java Builds neighborhoods node network using the new abstraction.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/enumerating/DatasetSession.java Updates session to accept the new node network abstraction.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/enumerating/common/DataNodeBuildHelper.java Adds neighborhoods node network construction.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/enumerating/common/AbstractDatasetInstance.java Adds activity methods (currently TODO) to satisfy new tuple lifecycle contract.
core/src/main/java/ai/timefold/solver/core/impl/neighborhood/NeighborhoodsBavetNodeNetwork.java Adds node-network implementation for neighborhoods.
core/src/main/java/ai/timefold/solver/core/impl/bavet/visual/NodeGraph.java Removes legacy Graphviz visualization implementation.
core/src/main/java/ai/timefold/solver/core/impl/bavet/visual/GraphSink.java Removes legacy visualization helper type.
core/src/main/java/ai/timefold/solver/core/impl/bavet/visual/GraphEdge.java Removes legacy visualization helper type.
core/src/main/java/ai/timefold/solver/core/impl/bavet/uni/PrecomputeUniNode.java Minor formatting change.
core/src/main/java/ai/timefold/solver/core/impl/bavet/uni/ForEachUnfilteredUniNode.java Implements root-node activity based on fact presence and downstream activity.
core/src/main/java/ai/timefold/solver/core/impl/bavet/uni/ForEachFilteredUniNode.java Implements activity based on “saw any input” semantics and downstream activity.
core/src/main/java/ai/timefold/solver/core/impl/bavet/uni/AbstractForEachUniNode.java Migrates ForEach root nodes to the new root-node base type.
core/src/main/java/ai/timefold/solver/core/impl/bavet/NodeNetwork.java Removes old node-network record in favor of the new abstraction.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/TupleLifecycle.java Makes tuple lifecycles activity-aware and updates profiling wrapper introspection.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/RightTupleLifecycleImpl.java Adds activity tracking and delegation behavior for right lifecycles.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/RightTupleLifecycle.java Extends right lifecycle contract with activity initialization and querying.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/RecordingTupleLifecycle.java Implements activity methods (always active) to satisfy new lifecycle contract.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/ProfilingTupleLifecycle.java Converts record to class and adds activity tracking delegation.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/LeftTupleLifecycleImpl.java Adds activity tracking and delegation behavior for left lifecycles.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/LeftTupleLifecycle.java Extends left lifecycle contract with activity initialization and querying.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/ConditionalTupleLifecycle.java Adds activity tracking so conditional lifecycles can be trimmed when upstream can’t produce.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/AggregatedTupleLifecycle.java Adds activity-aware downstream filtering/finalization.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/tuple/ActivitySupport.java Introduces the activity initialization/activation protocol.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/RecordAndReplayPropagator.java Adapts to new node-network abstraction and exposes tuple-production capability.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/Propagator.java Formatting-only change.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/ProfilingPropagator.java Formatting-only change.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/InnerConstraintProfiler.java Adds node-graph registration hook (replacing removed NodeGraph builder usage).
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractTwoInputNode.java Centralizes two-input initialization and activation logic.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractSingleInputNode.java Introduces default single-input activation forwarding logic.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractRootNode.java Replaces root-node interface with abstract base class implementing activity.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractPrecomputeNode.java Implements activity for precompute roots based on record/replay capability.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractNodeBuildHelper.java Removes old NodeNetwork building and adjusts layering logic for new node type hierarchy.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractNode.java Seals node hierarchy to enforce known node kinds for activation switching.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractMapNode.java Migrates map nodes to the new single-input base class.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractJoinNode.java Hooks join nodes into centralized two-input activation logic.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractIfExistsNode.java Implements can-produce logic consistent with ifExists/ifNotExists semantics.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractGroupNode.java Migrates group nodes to the new single-input base class.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractFlattenNode.java Migrates flatten nodes to the new single-input base class.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/AbstractConcatNode.java Implements concat’s “either side can produce” activation logic.
core/src/main/java/ai/timefold/solver/core/impl/bavet/AbstractSession.java Makes sessions generic over node-network type and exposes the built network.
core/src/main/java/ai/timefold/solver/core/impl/bavet/AbstractBavetNodeNetwork.java Adds new node-network abstraction including activation trimming and settle orchestration.
core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintRef.java Adds toString override for clearer logging/debugging output.

Comment thread docs/src/modules/ROOT/pages/constraints-and-score/performance.adoc Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 64 out of 64 changed files in this pull request and generated 4 comments.

triceo added 7 commits June 8, 2026 08:41
# Conflicts:
#	core/src/main/java/ai/timefold/solver/core/impl/bavet/common/RecordAndReplayPropagator.java
# Conflicts:
#	core/src/main/java/ai/timefold/solver/core/impl/bavet/uni/AbstractForEachUniNode.java

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 64 out of 64 changed files in this pull request and generated 2 comments.

Comment thread core/src/main/java/ai/timefold/solver/core/impl/bavet/AbstractSession.java Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 64 out of 64 changed files in this pull request and generated 1 comment.

@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
69.4% Coverage on New Code (required ≥ 70%)

See analysis details on SonarQube Cloud

@triceo triceo merged commit fe950f5 into TimefoldAI:main Jun 9, 2026
21 of 22 checks passed
@triceo triceo deleted the unlinking branch June 9, 2026 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants