1111__copyright__ = "Copyright (c) 2025 PySATL project"
1212__license__ = "SPDX-License-Identifier: MIT"
1313
14- from typing import TYPE_CHECKING , Any , Protocol , cast
14+ from typing import TYPE_CHECKING , Protocol , cast
1515
1616import numpy as np
1717
2020
2121if TYPE_CHECKING :
2222 from collections .abc import Mapping
23+ from typing import Any
2324
2425 from pysatl_core .distributions .computation import (
2526 AnalyticalComputation ,
2627 FittedComputationMethod ,
28+ Method ,
2729 )
2830 from pysatl_core .distributions .distribution import Distribution
29- from pysatl_core .distributions .registry .graph import RegistryView
3031 from pysatl_core .types import GenericCharacteristicName , LabelName
3132
3233
@@ -125,30 +126,16 @@ def _pick_analytical_method(
125126 f"Characteristic '{ state } ' provides no labeled analytical computations."
126127 ) from exc
127128
128- @staticmethod
129- def _pick_analytical_loop_method (
130- state : GenericCharacteristicName ,
131- view : RegistryView ,
132- ) -> Method [Any , Any ] | None :
133- """
134- Pick the first analytical self-loop method for a characteristic in a view.
135- """
136- loops = view .analytical_variants (state )
137- if not loops :
138- return None
139- return cast (Method [Any , Any ], next (iter (loops .values ())).method )
140-
141129 def query_method (
142130 self , state : GenericCharacteristicName , distr : Distribution , ** options : Any
143131 ) -> Method [Any , Any ]:
144132 """
145133 Resolve a computation method for the target characteristic.
146134
147135 Resolution order:
148- 1. Cached fitted method (if caching enabled)
149- 2. Analytical implementation for non-registry characteristics
150- 3. Analytical self-loop from the registry view
151- 4. Conversion path from analytical-loop characteristics via the graph
136+ 1. Analytical implementation from the distribution
137+ 2. Cached fitted method (if caching enabled)
138+ 3. Conversion path from an analytical characteristic via the graph
152139
153140 Parameters
154141 ----------
@@ -170,46 +157,34 @@ def query_method(
170157 If no analytical base exists, no conversion path is found,
171158 or a cycle is detected.
172159 """
173- # 1. Check cache if enabled
160+ # 1. Check for analytical implementation
161+ if state in distr .analytical_computations :
162+ return self ._pick_analytical_method (state , distr .analytical_computations [state ])
163+
164+ # 2. Check cache if enabled
174165 if self ._enable_caching :
175166 cached = self ._cache .get (state )
176167 if cached is not None :
177168 return cached
178169
179- # 2 . Require at least one analytical characteristic
170+ # 3 . Require at least one analytical characteristic
180171 if not distr .analytical_computations :
181172 raise RuntimeError (
182173 "Distribution provides no analytical computations to ground conversions."
183174 )
184175
185- # 3. Non-registry characteristics are resolved directly.
186- # It covers the situation where user is providing their analytical computation which isn't
187- # in the graph
188- registry = characteristic_registry ()
189- if state not in registry .declared_characteristics :
190- if state in distr .analytical_computations :
191- return self ._pick_analytical_method (state , distr .analytical_computations [state ])
192- raise RuntimeError (
193- f"Characteristic '{ state } ' is not declared in the registry and has no "
194- "analytical implementation in the distribution."
195- )
196-
197- # 4. Get filtered graph view for this distribution.
198- view = registry .view (distr )
176+ # 4. Get filtered graph view for this distribution
177+ reg = characteristic_registry ().view (distr )
199178
200179 self ._push_guard (distr , state )
201180 try :
202- loop_method = self ._pick_analytical_loop_method (state , view )
203- if loop_method is not None :
204- return loop_method
205-
206- # 5. Try each analytical-loop characteristic as a source
181+ # 5. Try each analytical characteristic as a source
207182 for src in distr .analytical_computations :
208- if not view . analytical_variants ( src ) :
209- continue
183+ if src == state :
184+ return self . _pick_analytical_method ( src , distr . analytical_computations [ src ])
210185
211186 # Find conversion path in the graph
212- path = view .find_path (src , state )
187+ path = reg .find_path (src , state )
213188 if not path :
214189 continue
215190
0 commit comments