55including recursive calls, crystallization, branching, and context management.
66"""
77
8+ import uuid
89from typing import Any , Callable , Dict , List , Optional , Union
9- from ..core .recursive_engine import ExecutionContext , get_default_executor
10+ from ..core .recursive_engine import ExecutionContext , get_default_executor , Continuation
1011from ..core .bifractal_trace import BifractalTrace
1112from ..core .memory_field import MemoryField
1213
@@ -54,31 +55,27 @@ def fibonacci(memory, context):
5455 if not hasattr (func , '_fracton_recursive' ) or not func ._fracton_recursive :
5556 raise ValueError (f"Function { func .__name__ } must be decorated with @recursive to use recurse()" )
5657
57- executor = get_default_executor ()
58+ # Check if we're inside a trampoline execution
59+ import threading
60+ current_thread = threading .current_thread ()
61+ in_trampoline = getattr (current_thread , '_fracton_in_trampoline' , False )
5862
59- # Record call in trace if provided
60- if trace :
61- entry_id = trace .record_call (func , context )
62-
63- try :
64- # Execute through the recursive engine
65- result = executor .execute (func , memory , context )
66-
67- # Record successful return
68- trace .record_return (func , context , result , entry_id )
69- return result
70-
71- except Exception as e :
72- # Record error
73- trace .record_error (func , context , e , entry_id )
74- raise
63+ if in_trampoline :
64+ # We're inside a trampoline, return a continuation
65+ if trace :
66+ entry_id = trace .record_call (func , context )
67+ return Continuation (func , memory , context )
7568 else :
76- # Execute without tracing
69+ # We're called directly, execute through the executor with trampoline
70+ executor = get_default_executor ()
7771 return executor .execute (func , memory , context )
7872
7973
80- def crystallize (data : Any , patterns : Optional [List ] = None ,
81- entropy_threshold : float = 0.3 ) -> Any :
74+ def crystallize (data : Any , memory : Optional [MemoryField ] = None ,
75+ context : Optional [ExecutionContext ] = None ,
76+ patterns : Optional [List ] = None ,
77+ entropy_threshold : float = 0.3 ,
78+ trace : Optional [BifractalTrace ] = None ) -> Any :
8279 """
8380 Crystallize data into stable structures based on entropy patterns.
8481
@@ -87,75 +84,134 @@ def crystallize(data: Any, patterns: Optional[List] = None,
8784
8885 Args:
8986 data: Data to crystallize
87+ memory: Optional memory field to store crystallized data
88+ context: Optional execution context for entropy awareness
9089 patterns: Optional list of patterns to reinforce
9190 entropy_threshold: Entropy level below which crystallization occurs
91+ trace: Optional bifractal trace for recording crystallization
9292
9393 Returns:
94- Crystallized data structure
94+ If memory is provided, returns the storage ID. Otherwise returns crystallized data.
9595
9696 Example:
9797 chaotic_data = {"values": [1, 5, 2, 8, 3, 7, 4, 6]}
9898 stable_data = fracton.crystallize(chaotic_data)
9999 # Result: {"values": [1, 2, 3, 4, 5, 6, 7, 8]} # Sorted
100100 """
101- # Calculate current entropy of data
102- current_entropy = _calculate_data_entropy (data )
101+ # Use context entropy if available, otherwise calculate from data
102+ if context and hasattr (context , 'entropy' ):
103+ current_entropy = context .entropy
104+ else :
105+ current_entropy = _calculate_data_entropy (data )
106+
107+ # Record in trace if provided
108+ if trace :
109+ trace_id = trace .record_operation (
110+ operation_type = "crystallization" ,
111+ context = context ,
112+ input_data = {"data" : data , "entropy_threshold" : entropy_threshold }
113+ )
103114
104115 if current_entropy <= entropy_threshold :
105116 # Already stable enough
106- return data
117+ crystallized_data = data
118+ else :
119+ # Apply crystallization based on data type
120+ if isinstance (data , dict ):
121+ crystallized_data = _crystallize_dict (data , patterns )
122+ elif isinstance (data , list ):
123+ crystallized_data = _crystallize_list (data , patterns )
124+ elif isinstance (data , str ):
125+ crystallized_data = _crystallize_string (data , patterns )
126+ else :
127+ # For other types, try to find inherent order
128+ crystallized_data = _crystallize_generic (data , patterns )
107129
108- # Apply crystallization based on data type
109- if isinstance (data , dict ):
110- return _crystallize_dict (data , patterns )
111- elif isinstance (data , list ):
112- return _crystallize_list (data , patterns )
113- elif isinstance (data , str ):
114- return _crystallize_string (data , patterns )
130+ # Update trace with result if provided
131+ if trace :
132+ trace .record_operation (
133+ operation_type = "crystallization_complete" ,
134+ context = context ,
135+ output_data = {"crystallized_data" : crystallized_data },
136+ parent_operation = trace_id
137+ )
138+
139+ # Store in memory if provided
140+ if memory :
141+ crystal_id = f"crystal_{ uuid .uuid4 ().hex [:8 ]} "
142+ memory .set (crystal_id , crystallized_data )
143+ return crystal_id
115144 else :
116- # For other types, try to find inherent order
117- return _crystallize_generic (data , patterns )
145+ return crystallized_data
118146
119147
120- def branch (condition : Union [bool , Callable ],
121- if_true : Callable , if_false : Callable ,
122- memory : MemoryField , context : ExecutionContext ) -> Any :
148+ def branch (condition : Union [bool , Callable , List ],
149+ if_true : Union [Callable , List , MemoryField ] = None ,
150+ if_false : Union [Callable , ExecutionContext , List ] = None ,
151+ memory : MemoryField = None , context : Union [ExecutionContext , List ] = None ) -> Any :
123152 """
124153 Entropy-aware conditional branching for recursive operations.
125154
126155 This function provides conditional execution that considers entropy levels
127156 and execution context for optimal path selection.
128157
129158 Args:
130- condition: Boolean condition or function that returns boolean
131- if_true: Function to call if condition is true
132- if_false: Function to call if condition is false
133- memory: Shared memory field
134- context: Execution context
159+ condition: Boolean condition, function that returns boolean, or list of functions
160+ if_true: Function to call if condition is true, or MemoryField for multi-branch
161+ if_false: Function to call if condition is false, or contexts for multi-branch
162+ memory: Shared memory field (traditional mode)
163+ context: Execution context or list of contexts for multi-branch
135164
136165 Returns:
137- Result of the selected branch function
166+ Result of the selected branch function, or list of results for multi-branch
138167
139168 Example:
169+ # Simple branch
140170 result = fracton.branch(
141171 context.entropy > 0.5,
142172 high_entropy_path,
143173 low_entropy_path,
144174 memory,
145175 context
146176 )
177+
178+ # Multi-branch over contexts: branch(functions_list, memory, contexts_list)
179+ results = fracton.branch(
180+ [func1, func2],
181+ memory,
182+ [context1, context2]
183+ )
147184 """
185+ # Handle multi-branch case: branch([func1, func2], memory, [ctx1, ctx2])
186+ if isinstance (condition , list ) and if_false is not None and isinstance (if_false , list ):
187+ functions = condition
188+ memory_field = if_true # Second arg is memory
189+ contexts = if_false # Third arg is contexts list
190+ results = []
191+ for func , ctx in zip (functions , contexts ):
192+ # For non-recursive functions, call directly
193+ if hasattr (func , '_fracton_recursive' ) and func ._fracton_recursive :
194+ result = recurse (func , memory_field , ctx )
195+ else :
196+ result = func (memory_field , ctx )
197+ results .append (result )
198+ return results
199+
200+ # Handle traditional branch case: branch(condition, if_true, if_false, memory, context)
148201 # Evaluate condition if it's a callable
149202 if callable (condition ):
150203 condition_result = condition (memory , context )
151204 else :
152205 condition_result = condition
153206
154207 # Select and execute branch
155- if condition_result :
156- return recurse (if_true , memory , context )
208+ selected_func = if_true if condition_result else if_false
209+
210+ # For non-recursive functions, call directly
211+ if hasattr (selected_func , '_fracton_recursive' ) and selected_func ._fracton_recursive :
212+ return recurse (selected_func , memory , context )
157213 else :
158- return recurse ( if_false , memory , context )
214+ return selected_func ( memory , context )
159215
160216
161217def merge_contexts (* contexts : ExecutionContext ) -> ExecutionContext :
0 commit comments