hdim-opt 1.1.3__py3-none-any.whl → 1.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hdim_opt/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # hdim_opt/__init__.py
2
2
 
3
3
  # package version
4
- __version__ = "1.1.3"
4
+ __version__ = "1.2.2"
5
5
  __all__ = ['quasar', 'hds', 'sobol', 'sensitivity', 'test_functions', 'quasar_helpers'] # available for star imports
6
6
 
7
7
  # import core components
@@ -553,7 +553,7 @@ def sample(n_samples, bounds,
553
553
  # dark visualization parameters for better sample visuals
554
554
 
555
555
  # samples
556
- fig, ax = plt.subplots(1,2,figsize=(11,5.5))
556
+ fig, ax = plt.subplots(1,2,figsize=(9,5))
557
557
 
558
558
  ax[0].scatter(hds_sequence_plot[:, 0], hds_sequence_plot[:, 1], s=0.67, zorder=5, color='deepskyblue',
559
559
  label='HDS Samples')
@@ -58,9 +58,12 @@ def initialize_population(popsize, bounds, init, hds_weights, seed, verbose):
58
58
  print(f'Initializing: Random population (N={popsize}, D={n_dimensions}).')
59
59
  initial_population = np.random.uniform(low=bounds[:, 0], high=bounds[:, 1], size=(popsize, n_dimensions))
60
60
  else:
61
- initial_population = init
61
+ if init.ndim == 1:
62
+ initial_population = init.reshape(-1,1)
63
+ else:
64
+ initial_population = init
62
65
  if verbose:
63
- custom_popsize, custom_n_dimensions = init.shape
66
+ custom_popsize, custom_n_dimensions = initial_population.shape
64
67
  print(f'Initializing: Custom population (N={custom_popsize}, D={custom_n_dimensions}).')
65
68
 
66
69
  return initial_population
@@ -260,14 +263,13 @@ def evolve_generation(obj_function, population, fitnesses, best_solution,
260
263
 
261
264
  return new_population, new_fitnesses
262
265
 
263
- def covariance_reinit(population, current_fitnesses, bounds, vectorized):
266
+ def asym_reinit(population, current_fitnesses, bounds, reinit_method, seed, vectorized):
264
267
  '''
265
268
  Objective:
266
269
  - Reinitializes the worst 33% solutions in the population.
267
- - Locations are determined based on a Gaussian distribution from the covariance matrix of 25% best solutions.
268
- - Noise is added to enhance diversity.
269
- - Probability decays to 33% at the 33% generation.
270
- - Conceptualizes particles tunneling to a more stable location.
270
+ - Locations are determined based on either:
271
+ - 'covariance' (default): Gaussian distribution from the covariance of 25% best solutions (exploitation).
272
+ - 'sobol': Uniformly Sobol distributed within the bounds (exploration).
271
273
  '''
272
274
 
273
275
  # reshape depending on vectorized input
@@ -276,60 +278,90 @@ def covariance_reinit(population, current_fitnesses, bounds, vectorized):
276
278
  else:
277
279
  popsize, dimensions = population.shape
278
280
 
279
- # handle case where not enough points for covariance matrix
281
+ # handle case where not enough points for reliable covariance matrix
280
282
  if popsize < dimensions + 1:
281
283
  return population
282
-
283
- # keep 25% of best solutions
284
- num_to_keep_factor = 0.25
285
- num_to_keep = int(popsize * num_to_keep_factor)
286
- if num_to_keep <= dimensions:
287
- num_to_keep = dimensions + 1 # minimum sample size scaled by dimensions
288
-
289
- # identify best solutions to calculate covariance gaussian model
290
- sorted_indices = np.argsort(current_fitnesses)
291
- best_indices = sorted_indices[:num_to_keep]
292
- if vectorized:
293
- best_solutions = population[:, best_indices]
294
- else:
295
- best_solutions = population[best_indices]
296
284
 
297
- # learn full-covariance matrix
298
- if vectorized:
299
- mean_vector = np.mean(best_solutions, axis=1)
300
- cov_matrix = np.cov(best_solutions)
301
- else:
302
- mean_vector = np.mean(best_solutions, axis=0)
303
- cov_matrix = np.cov(best_solutions, rowvar=False)
304
-
305
- # add epsilon to the diagonal to prevent singular matrix issues
306
- cov_matrix += np.eye(dimensions) * epsilon
307
-
308
285
  # identify solutions to be reset
309
286
  reset_population = 0.33
310
287
  num_to_replace = int(popsize * reset_population)
288
+ if num_to_replace == 0:
289
+ return population
290
+
291
+ sorted_indices = np.argsort(current_fitnesses)
311
292
  worst_indices = sorted_indices[-num_to_replace:]
293
+
294
+ # initializing new solutions
295
+ new_solutions = None
296
+
297
+ # covariance reinitalization; exploitation
298
+ if reinit_method == 'covariance':
299
+
300
+ # keep 25% of best solutions
301
+ num_to_keep_factor = 0.25
302
+ num_to_keep = int(popsize * num_to_keep_factor)
303
+ if num_to_keep <= dimensions:
304
+ num_to_keep = dimensions + 1 # minimum sample size scaled by dimensions
305
+
306
+ # identify best solutions to calculate covariance gaussian model
307
+ best_indices = sorted_indices[:num_to_keep]
308
+ if vectorized:
309
+ best_solutions = population[:, best_indices]
310
+ else:
311
+ best_solutions = population[best_indices]
312
+
313
+ # learn full-covariance matrix
314
+ if vectorized:
315
+ mean_vector = np.mean(best_solutions, axis=1)
316
+ cov_matrix = np.cov(best_solutions)
317
+ else:
318
+ mean_vector = np.mean(best_solutions, axis=0)
319
+ cov_matrix = np.cov(best_solutions, rowvar=False)
312
320
 
313
- # new solutions sampled from multivariate normal distribution
314
- if vectorized:
315
- new_solutions_sampled = np.random.multivariate_normal(mean=mean_vector, cov=cov_matrix, size=num_to_replace).T
316
- else:
321
+ # add epsilon to the diagonal to prevent singular matrix issues
322
+ cov_matrix += np.eye(dimensions) * epsilon
323
+
324
+ # new solutions sampled from multivariate normal distribution
317
325
  new_solutions_sampled = np.random.multivariate_normal(mean=mean_vector, cov=cov_matrix, size=num_to_replace)
318
-
319
- # add noise for exploration
320
- noise_scale = (bounds[:, 1] - bounds[:, 0]) / 20.0
321
- if vectorized:
322
- noise = np.random.normal(0, noise_scale[:, np.newaxis], size=new_solutions_sampled.shape)
323
- new_solutions = new_solutions_sampled + noise
324
- else:
325
- noise = np.random.normal(0, noise_scale, size=new_solutions_sampled.shape)
326
- new_solutions = new_solutions_sampled + noise
326
+
327
+ # add noise for exploration
328
+ noise_scale = (bounds[:, 1] - bounds[:, 0]) / 20.0
327
329
 
328
- # clip new solutions to bounds
329
- if vectorized:
330
- population[:, worst_indices] = np.clip(new_solutions, bounds[:, np.newaxis, 0], bounds[:, np.newaxis, 1])
331
- else:
332
- population[worst_indices] = np.clip(new_solutions, bounds[:, 0], bounds[:, 1])
330
+ # reshape
331
+ if vectorized:
332
+ new_solutions_sampled = new_solutions_sampled.T
333
+ noise = np.random.normal(0, noise_scale[:, np.newaxis], size=new_solutions_sampled.shape)
334
+ new_solutions = new_solutions_sampled + noise
335
+ else:
336
+ noise = np.random.normal(0, noise_scale, size=new_solutions_sampled.shape)
337
+ new_solutions = new_solutions_sampled + noise
338
+
339
+ # sobol reinitialization (high exploration)
340
+ elif reinit_method == 'sobol':
341
+
342
+ # generate sobol samples
343
+ sobol_sampler = stats.qmc.Sobol(d=dimensions, seed=seed)
344
+ sobol_samples_unit = sobol_sampler.random(n=num_to_replace)
345
+
346
+ bounds_low = bounds[:, 0]
347
+ bounds_high = bounds[:, 1]
348
+ scaled_samples = stats.qmc.scale(sobol_samples_unit, bounds_low, bounds_high)
349
+
350
+ # reshape
351
+ if vectorized:
352
+ new_solutions = scaled_samples.T
353
+ else:
354
+ new_solutions = scaled_samples
355
+
356
+
357
+ # update the selected worst indices population
358
+ if new_solutions is not None:
359
+ if vectorized:
360
+ population[:, worst_indices] = np.clip(new_solutions,
361
+ bounds[:, np.newaxis, 0],
362
+ bounds[:, np.newaxis, 1])
363
+ else:
364
+ population[worst_indices] = np.clip(new_solutions, bounds[:, 0], bounds[:, 1])
333
365
 
334
366
  return population
335
367
 
@@ -342,7 +374,7 @@ def optimize(func, bounds, args=(),
342
374
  patience=np.inf, vectorized=False,
343
375
  hds_weights=None, kwargs={},
344
376
  constraints=None, constraint_penalty=1e9,
345
- reinitialization=True,
377
+ reinitialization=True, reinitialization_method='covariance',
346
378
  verbose=True, plot_solutions=True, num_to_plot=10, plot_contour=True,
347
379
  workers=1, seed=None
348
380
  ):
@@ -351,7 +383,7 @@ def optimize(func, bounds, args=(),
351
383
  - Finds the optimal solution for a given objective function.
352
384
  - Designed for non-differentiable, high-dimensional problems.
353
385
  - Test functions available for local testing, called as hdim_opt.test_functions.function_name.
354
- - Existing test functions: [rastrigin, ackley, sinusoid, sphere]
386
+ - Existing test functions: [rastrigin, ackley, sinusoid, sphere, shubert].
355
387
 
356
388
  Inputs:
357
389
  - func: Objective function to minimize.
@@ -400,9 +432,13 @@ def optimize(func, bounds, args=(),
400
432
  }
401
433
  - constraint_penalty: Penalty applied to each constraint violated, defaults to 1e12.
402
434
 
403
- - covariance_reinit: Boolean to disable covariance reinitialization if needed.
435
+ - reinitialization: Boolean to disable covariance reinitialization if needed.
404
436
  - For cases where the population size is computationally prohibitive.
405
437
  - Disabled by default for 1D problems.
438
+ - reinitialization_method: Type of re-sampling to use in the asymptotic reinitialization.
439
+ - Options are ['covariance', 'sobol'].
440
+ - 'covariance' (exploitative) is default for most problems.
441
+ - 'sobol' (explorative) is optional, for high exploration and faster computation.
406
442
 
407
443
  - verbose: Displays prints and plots.
408
444
  - Mutation factor distribution shown with hdim_opt.test_functions.plot_mutations()
@@ -612,7 +648,7 @@ def optimize(func, bounds, args=(),
612
648
  else:
613
649
  reinit_proba = 0.0
614
650
  if np.random.rand() < reinit_proba:
615
- population = covariance_reinit(population, current_fitnesses, bounds, vectorized=vectorized)
651
+ population = asym_reinit(population, current_fitnesses, bounds, reinitialization_method, seed, vectorized=vectorized)
616
652
 
617
653
  # clip population to bounds
618
654
  if vectorized:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hdim_opt
3
- Version: 1.1.3
3
+ Version: 1.2.2
4
4
  Summary: Optimization toolkit for high-dimensional, non-differentiable problems.
5
5
  Author-email: Julian Soltes <jsoltes@regis.edu>
6
6
  License: MIT
@@ -0,0 +1,11 @@
1
+ hdim_opt/__init__.py,sha256=eGhYIxj6AUhhlfqgAHtPQdul64gYYLaWl8esUs-vkgI,477
2
+ hdim_opt/hyperellipsoid_sampling.py,sha256=c34JkVciZbdAXjdfNjfC4h5NsrT2CD7Epsxpef5a1xY,24625
3
+ hdim_opt/quasar_helpers.py,sha256=zTgar2EuWs4MLSLEO7HRcP7At1xbXLP3q4Gg7-GrggQ,14799
4
+ hdim_opt/quasar_optimization.py,sha256=cSF_aOijVhdtvr7VEBUNVyBQ1--1s8cOuWZMuPogf5A,32093
5
+ hdim_opt/sobol_sampling.py,sha256=Xe_Zzs13xMxCben17gT85lFsoV-GKVOAAgi7lMxnlBI,912
6
+ hdim_opt/sobol_sensitivity.py,sha256=1ebeDSTmcLn03_MKDGiyJJ7r_ZSNCq2AKNcTX-hI23A,4384
7
+ hdim_opt/test_functions.py,sha256=RqjKYIiwAqWplGUsH4oPHLBrVdnLRyw7f0dJX5iyJ4g,2821
8
+ hdim_opt-1.2.2.dist-info/METADATA,sha256=jId-zu3VAQTuQFgwlSQqKTgnCtwbORXuLbqsCVbSvA4,3130
9
+ hdim_opt-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
+ hdim_opt-1.2.2.dist-info/top_level.txt,sha256=1KtWo9tEfEK3GC8D43cwVsC8yVG2Kc-9pl0hhcDjw4o,9
11
+ hdim_opt-1.2.2.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- hdim_opt/__init__.py,sha256=rQp14fICPy_GoZrp-sDBopItLr3yR20C7-3U4tgQxEc,477
2
- hdim_opt/hyperellipsoid_sampling.py,sha256=QmbpFnZheCkwR5FOWNQS5C-FxDiNVKG97JPLqYH8G5I,24628
3
- hdim_opt/quasar_helpers.py,sha256=zTgar2EuWs4MLSLEO7HRcP7At1xbXLP3q4Gg7-GrggQ,14799
4
- hdim_opt/quasar_optimization.py,sha256=NOee1-e7mj3zUvbf-HI4a-JGrOwflG0f87HCVymANWA,30578
5
- hdim_opt/sobol_sampling.py,sha256=Xe_Zzs13xMxCben17gT85lFsoV-GKVOAAgi7lMxnlBI,912
6
- hdim_opt/sobol_sensitivity.py,sha256=1ebeDSTmcLn03_MKDGiyJJ7r_ZSNCq2AKNcTX-hI23A,4384
7
- hdim_opt/test_functions.py,sha256=RqjKYIiwAqWplGUsH4oPHLBrVdnLRyw7f0dJX5iyJ4g,2821
8
- hdim_opt-1.1.3.dist-info/METADATA,sha256=XP4iX4mdgSVX1dAyW3AwNTn5YVfmbdwMN4-tZdjMBfI,3130
9
- hdim_opt-1.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
10
- hdim_opt-1.1.3.dist-info/top_level.txt,sha256=1KtWo9tEfEK3GC8D43cwVsC8yVG2Kc-9pl0hhcDjw4o,9
11
- hdim_opt-1.1.3.dist-info/RECORD,,