@@ -39,7 +39,7 @@ public OptimizationResults Optimize(OptimizationSnapshot os)
3939 // Process and store results
4040 foreach ( var deviceId in uniqueDeviceIds )
4141 {
42- if ( rxAdjRssiDict . TryGetValue ( deviceId , out var rxAdjRssi ) &&
42+ if ( rxAdjRssiDict . TryGetValue ( deviceId , out var rxAdjRssi ) &&
4343 nodeAbsorptions . TryGetValue ( deviceId , out var absorption ) )
4444 {
4545 results . RxNodes [ deviceId ] = new ProposedValues
@@ -59,7 +59,7 @@ public OptimizationResults Optimize(OptimizationSnapshot os)
5959 return results ;
6060 }
6161
62- private ( Dictionary < string , double > RxAdjRssi , Dictionary < ( string , string ) , double > PathAbsorption , double Error )
62+ private ( Dictionary < string , double > RxAdjRssi , Dictionary < ( string , string ) , double > PathAbsorption , double Error )
6363 OptimizeRxAdjRssiAndPathAbsorption ( List < Measure > allNodes , List < string > uniqueDeviceIds , ConfigOptimization optimization )
6464 {
6565 var pathPairs = new HashSet < ( string , string ) > ( allNodes . Select ( n => ( Min ( n . Rx . Id , n . Tx . Id ) , Max ( n . Rx . Id , n . Tx . Id ) ) ) ) ;
@@ -119,31 +119,48 @@ public OptimizationResults Optimize(OptimizationSnapshot os)
119119 return ( rxAdjRssiDict , pathAbsorptionDict , result . FunctionInfoAtMinimum . Value ) ;
120120 }
121121
122- private Dictionary < string , double > OptimizeNodeAbsorptions ( List < Measure > allNodes , List < string > uniqueDeviceIds ,
122+ private Dictionary < string , double > OptimizeNodeAbsorptions ( List < Measure > allNodes , List < string > uniqueDeviceIds ,
123123 Dictionary < string , double > rxAdjRssiDict , Dictionary < ( string , string ) , double > pathAbsorptionDict , ConfigOptimization optimization )
124124 {
125- var obj = ObjectiveFunction . ValueAndGradient ( x =>
126- {
127- // Objective function (error calculation) remains the same
128- var value = CalculateError ( allNodes , rxAdjRssiDict , pathAbsorptionDict : absorptionDict ) ;
129-
130- // Numerically approximate the gradient
131- var gradient = new double [ x . Count ] ;
132- double epsilon = 1e-5 ;
133-
134- for ( int i = 0 ; i < x . Count ; i ++ )
135- {
136- var xPlusEps = x . Clone ( ) ;
137- xPlusEps [ i ] += epsilon ;
125+ // Fix: Use ObjectiveFunction.Gradient() instead of ValueAndGradient
126+ var obj = ObjectiveFunction . Gradient (
127+ x => {
128+ var nodeAbsorptionDict = new Dictionary < string , double > ( ) ;
129+ for ( int i = 0 ; i < uniqueDeviceIds . Count ; i ++ )
130+ {
131+ var absorption = x [ i ] ;
132+ if ( absorption < optimization ? . AbsorptionMin || absorption > optimization ? . AbsorptionMax )
133+ return double . PositiveInfinity ;
134+ nodeAbsorptionDict [ uniqueDeviceIds [ i ] ] = absorption ;
135+ }
138136
139- var errorPlusEps = CalculateError ( allNodes , rxAdjRssiDict , pathAbsorptionDict : absorptionDict ) ;
140- gradient [ i ] = ( errorPlusEps - value ) / epsilon ;
141- }
137+ return CalculateError ( allNodes , rxAdjRssiDict , nodeAbsorptionDict : nodeAbsorptionDict ) ;
138+ } ,
139+ x => {
140+ var nodeAbsorptionDict = new Dictionary < string , double > ( ) ;
141+ for ( int i = 0 ; i < uniqueDeviceIds . Count ; i ++ )
142+ {
143+ nodeAbsorptionDict [ uniqueDeviceIds [ i ] ] = x [ i ] ;
144+ }
145+
146+ // Numerically approximate the gradient
147+ var gradient = Vector < double > . Build . Dense ( x . Count ) ;
148+ double epsilon = 1e-5 ;
149+ double baseError = CalculateError ( allNodes , rxAdjRssiDict , nodeAbsorptionDict : nodeAbsorptionDict ) ;
142150
143- return ( value , Vector < double > . Build . Dense ( gradient ) ) ;
144- } ) ;
151+ for ( int i = 0 ; i < x . Count ; i ++ )
152+ {
153+ var tempDict = new Dictionary < string , double > ( nodeAbsorptionDict ) ;
154+ tempDict [ uniqueDeviceIds [ i ] ] += epsilon ;
155+
156+ var errorPlusEps = CalculateError ( allNodes , rxAdjRssiDict , nodeAbsorptionDict : tempDict ) ;
157+ gradient [ i ] = ( errorPlusEps - baseError ) / epsilon ;
158+ }
159+
160+ return gradient ;
161+ } ) ;
145162
146- var initialGuess = Vector < double > . Build . Dense ( uniqueDeviceIds . Count ,
163+ var initialGuess = Vector < double > . Build . Dense ( uniqueDeviceIds . Count ,
147164 ( optimization ? . AbsorptionMax - optimization ? . AbsorptionMin ) / 2 + optimization ? . AbsorptionMin ?? 3d ) ;
148165
149166 var solver = new BfgsMinimizer ( 1e-7 , 1e-7 , 1e-7 ) ;
@@ -158,7 +175,7 @@ private Dictionary<string, double> OptimizeNodeAbsorptions(List<Measure> allNode
158175 return nodeAbsorptions ;
159176 }
160177
161- private double CalculateError ( List < Measure > nodes , Dictionary < string , double > rxAdjRssiDict ,
178+ private double CalculateError ( List < Measure > nodes , Dictionary < string , double > rxAdjRssiDict ,
162179 Dictionary < string , double > nodeAbsorptionDict = null , Dictionary < ( string , string ) , double > pathAbsorptionDict = null )
163180 {
164181 return nodes . Select ( n =>
@@ -189,4 +206,4 @@ private double CalculateError(List<Measure> nodes, Dictionary<string, double> rx
189206
190207 private static string Min ( string a , string b ) => string . Compare ( a , b ) < 0 ? a : b ;
191208 private static string Max ( string a , string b ) => string . Compare ( a , b ) >= 0 ? a : b ;
192- }
209+ }
0 commit comments