2020using ILGPU . Tests ;
2121using System . Linq ;
2222using System . Numerics ;
23+ using System . Runtime . CompilerServices ;
2324using Xunit ;
2425using Xunit . Abstractions ;
2526
@@ -34,11 +35,18 @@ public abstract partial class OptimizationTests : TestBase
3435 protected OptimizationTests ( ITestOutputHelper output , TestContext testContext )
3536 : base ( output , testContext )
3637 { }
37-
38+
3839#if NET7_0_OR_GREATER
39-
40+
4041 #region Objectives
41-
42+
43+ public interface IPredefineTestFunction
44+ {
45+ float Result { get ; }
46+ float [ ] LowerBounds { get ; }
47+ float [ ] UpperBounds { get ; }
48+ }
49+
4250 public readonly record struct DistanceF32x2 ( float Constant ) :
4351 IOptimizationFunction < Float32x2 , float , float >
4452 {
@@ -60,7 +68,271 @@ public float Evaluate(
6068 public bool CurrentIsBetter ( float current , float proposed ) =>
6169 current <= proposed ;
6270 }
63-
71+
72+ /// <summary>
73+ /// Represents the Himmelblau function:
74+ /// https://en.wikipedia.org/wiki/Test_functions_for_optimization
75+ /// </summary>
76+ public readonly record struct HimmelblauFunction :
77+ IOptimizationFunction < Float32x2 , float , float > ,
78+ IPredefineTestFunction
79+ {
80+ private static readonly float [ ] GlobalLowerBounds = new float [ ]
81+ {
82+ - 5.0f , - 5.0f
83+ } ;
84+
85+ private static readonly float [ ] GlobalUpperBounds = new float [ ]
86+ {
87+ 5.0f , 5.0f
88+ } ;
89+
90+ /// <summary>
91+ /// The optimal result.
92+ /// </summary>
93+ public const float GlobalResult = 0.0f ;
94+
95+ /// <summary>
96+ /// Evaluates the Himmelblau function.
97+ /// </summary>
98+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
99+ public static float Evaluate ( float x , float y )
100+ {
101+ float first = ( x * x + y - 11 ) ;
102+ float second = ( x + y * y - 7 ) ;
103+ return first * first + second * second ;
104+ }
105+
106+ public float Result => GlobalResult ;
107+ public float [ ] LowerBounds => GlobalLowerBounds ;
108+ public float [ ] UpperBounds => GlobalUpperBounds ;
109+
110+ public float Evaluate (
111+ LongIndex1D index ,
112+ Index1D dimension ,
113+ SingleVectorView < Float32x2 > positionView )
114+ {
115+ var first = positionView [ 0 ] ;
116+ return Evaluate ( first . X , first . Y ) ;
117+ }
118+
119+ public bool CurrentIsBetter ( float current , float proposed ) =>
120+ current < proposed ;
121+ }
122+
123+ /// <summary>
124+ /// Represents the Easom function:
125+ /// https://en.wikipedia.org/wiki/Test_functions_for_optimization
126+ /// </summary>
127+ public readonly record struct EasomFunction :
128+ IOptimizationFunction < Float32x2 , float , float > ,
129+ IPredefineTestFunction
130+ {
131+ private static readonly float [ ] GlobalLowerBounds = new float [ ]
132+ {
133+ - 100.0f , - 100.0f
134+ } ;
135+
136+ private static readonly float [ ] GlobalUpperBounds = new float [ ]
137+ {
138+ 100.0f , 100.0f
139+ } ;
140+
141+ /// <summary>
142+ /// The optimal result.
143+ /// </summary>
144+ public const float GlobalResult = - 1.0f ;
145+
146+ public float Result => GlobalResult ;
147+ public float [ ] LowerBounds => GlobalLowerBounds ;
148+ public float [ ] UpperBounds => GlobalUpperBounds ;
149+
150+ /// <summary>
151+ /// Evaluates the Easom function.
152+ /// </summary>
153+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
154+ public static float Evaluate ( float x , float y )
155+ {
156+ float xPart = x - XMath . PI ;
157+ float yPart = y - XMath . PI ;
158+ return - XMath . Cos ( x ) * XMath . Cos ( y ) *
159+ XMath . Exp ( - ( xPart * xPart + yPart * yPart ) ) ;
160+ }
161+ public float Evaluate (
162+ LongIndex1D index ,
163+ Index1D dimension ,
164+ SingleVectorView < Float32x2 > positionView )
165+ {
166+ var first = positionView [ 0 ] ;
167+ return Evaluate ( first . X , first . Y ) ;
168+ }
169+
170+ public bool CurrentIsBetter ( float current , float proposed ) =>
171+ current < proposed ;
172+ }
173+
174+ /// <summary>
175+ /// Represents the Shaffer function N4:
176+ /// https://en.wikipedia.org/wiki/Test_functions_for_optimization
177+ /// </summary>
178+ public readonly record struct ShafferFunction4 :
179+ IOptimizationFunction < Float32x2 , float , float > ,
180+ IPredefineTestFunction
181+ {
182+ private static readonly float [ ] GlobalLowerBounds = new float [ ]
183+ {
184+ - 100.0f , - 100.0f
185+ } ;
186+
187+ private static readonly float [ ] GlobalUpperBounds = new float [ ]
188+ {
189+ 100.0f , 100.0f
190+ } ;
191+
192+ /// <summary>
193+ /// The optimal result.
194+ /// </summary>
195+ public const float GlobalResult = 0.292579f ;
196+
197+ public float Result => GlobalResult ;
198+ public float [ ] LowerBounds => GlobalLowerBounds ;
199+ public float [ ] UpperBounds => GlobalUpperBounds ;
200+
201+ /// <summary>
202+ /// Evaluates the Shaffer function.
203+ /// </summary>
204+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
205+ public static float Evaluate ( float x , float y )
206+ {
207+ float cos = XMath . Cos ( XMath . Sin ( XMath . Abs ( x * x - y * y ) ) ) ;
208+ float nominator = cos * cos - 0.5f ;
209+ float denominator = 1 + 0.001f * ( x * x + y * y ) ;
210+ return 0.5f + nominator / ( denominator * denominator ) ;
211+ }
212+ public float Evaluate (
213+ LongIndex1D index ,
214+ Index1D dimension ,
215+ SingleVectorView < Float32x2 > positionView )
216+ {
217+ var first = positionView [ 0 ] ;
218+ return Evaluate ( first . X , first . Y ) ;
219+ }
220+
221+ public bool CurrentIsBetter ( float current , float proposed ) =>
222+ current < proposed ;
223+ }
224+
225+ /// <summary>
226+ /// Represents the Rosenbrock function constrained to a disk
227+ /// https://en.wikipedia.org/wiki/Test_functions_for_optimization
228+ /// </summary>
229+ public readonly record struct RosenbrockDisk :
230+ IOptimizationFunction < Float32x2 , float , float > ,
231+ IPredefineTestFunction
232+ {
233+ private static readonly float [ ] GlobalLowerBounds = new float [ ]
234+ {
235+ - 1.5f , - 1.5f
236+ } ;
237+
238+ private static readonly float [ ] GlobalUpperBounds = new float [ ]
239+ {
240+ 1.5f , 1.5f
241+ } ;
242+
243+ /// <summary>
244+ /// The optimal result.
245+ /// </summary>
246+ public const float GlobalResult = 0.0f ;
247+
248+ public float Result => GlobalResult ;
249+ public float [ ] LowerBounds => GlobalLowerBounds ;
250+ public float [ ] UpperBounds => GlobalUpperBounds ;
251+
252+ /// <summary>
253+ /// Evaluates the constrained Rosenbrock function.
254+ /// </summary>
255+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
256+ public static float Evaluate ( float x , float y )
257+ {
258+ float xMin = 1.0f - x ;
259+ float x2 = x * x ;
260+ float result = xMin * xMin + 100.0f * ( y - x2 ) * ( y - x2 ) ;
261+ if ( x * x + y * y <= 2.0f )
262+ return result ;
263+ return float . MaxValue ;
264+ }
265+
266+ public float Evaluate (
267+ LongIndex1D index ,
268+ Index1D dimension ,
269+ SingleVectorView < Float32x2 > positionView )
270+ {
271+ var first = positionView [ 0 ] ;
272+ return Evaluate ( first . X , first . Y ) ;
273+ }
274+
275+ public bool CurrentIsBetter ( float current , float proposed ) =>
276+ current < proposed ;
277+ }
278+
279+ /// <summary>
280+ /// Represents the Gomez and Levy function:
281+ /// https://en.wikipedia.org/wiki/Test_functions_for_optimization
282+ /// </summary>
283+ public readonly record struct GomezAndLevyFunction :
284+ IOptimizationFunction < Float32x2 , float , float > ,
285+ IPredefineTestFunction
286+ {
287+ private static readonly float [ ] GlobalLowerBounds = new float [ ]
288+ {
289+ - 1.0f , - 1.0f
290+ } ;
291+
292+ private static readonly float [ ] GlobalUpperBounds = new float [ ]
293+ {
294+ 0.75f , 1.0f
295+ } ;
296+
297+ /// <summary>
298+ /// The optimal result.
299+ /// </summary>
300+ public const float GlobalResult = - 1.031628453f ;
301+
302+ public float Result => GlobalResult ;
303+ public float [ ] LowerBounds => GlobalLowerBounds ;
304+ public float [ ] UpperBounds => GlobalUpperBounds ;
305+
306+ /// <summary>
307+ /// Evaluates the constrained Gomez and Levy function.
308+ /// </summary>
309+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
310+ public static float Evaluate ( float x , float y )
311+ {
312+ float x2 = x * x ;
313+ float x4 = x2 * x2 ;
314+ float y2 = y * y ;
315+ float y4 = y2 * y2 ;
316+ float result = 4.0f * x2 + 2.1f * x4 + 1.0f / 3.0f * x4 * x2 +
317+ x * y - 4.0f * y2 + 4.0f * y4 ;
318+ float sin = XMath . Sin ( 2.0f * XMath . PI * y ) ;
319+ float conditionValue = - XMath . Sin ( 4.0f * XMath . PI * x ) + 2.0f * sin * sin ;
320+ return conditionValue < 1.5f ? result : float . MaxValue ;
321+ }
322+
323+ public float Evaluate (
324+ LongIndex1D index ,
325+ Index1D dimension ,
326+ SingleVectorView < Float32x2 > positionView )
327+ {
328+ var first = positionView [ 0 ] ;
329+ return Evaluate ( first . X , first . Y ) ;
330+ }
331+
332+ public bool CurrentIsBetter ( float current , float proposed ) =>
333+ current < proposed ;
334+ }
335+
64336 #endregion
65337
66338 #region MemberData
@@ -129,7 +401,7 @@ public static TheoryData<
129401
130402 #endregion
131403
132- [ SkippableTheory ( ) ]
404+ [ SkippableTheory ]
133405 [ MemberData ( nameof ( TestData ) ) ]
134406 public void ParticleSwarmOptimization <
135407 TFunc ,
@@ -157,7 +429,7 @@ public void ParticleSwarmOptimization<
157429 Skip . If (
158430 Accelerator . AcceleratorType == AcceleratorType . CPU &&
159431 optimizerConfig . NumIterations * optimizerConfig . NumParticles > 2048 ) ;
160-
432+
161433 const int Seed = 24404699 ;
162434 using var pso = new PSO <
163435 TNumericType ,
@@ -185,7 +457,7 @@ public void ParticleSwarmOptimization<
185457 best ,
186458 optimizerConfig . NumIterations ) ;
187459 stream . Synchronize ( ) ;
188-
460+
189461 // Check result
190462 Assert . True (
191463 result . Result - delta <= expected ,
0 commit comments