coco-experiment 2.8.1__tar.gz → 2.8.3__tar.gz

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.
Files changed (23) hide show
  1. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/.gitignore +2 -0
  2. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/PKG-INFO +7 -8
  3. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/pyproject.toml +14 -8
  4. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/__init__.py +1 -0
  5. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/_version.py +1 -1
  6. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/coco.c +44 -18
  7. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/interface.pyx +1 -1
  8. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/noiser.py +20 -1
  9. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/utilities.py +9 -8
  10. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/LICENSE +0 -0
  11. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/README.md +0 -0
  12. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/meson.build +0 -0
  13. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/scripts/run-doctest.py +0 -0
  14. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/bare_problem.pyx +0 -0
  15. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/coco.h +0 -0
  16. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/download_example.py +0 -0
  17. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/exceptions.py +0 -0
  18. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/src/cocoex/solvers.py +0 -0
  19. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/tests/bbob2009_testcases.txt +0 -0
  20. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/tests/bbob2009_testcases2.txt +0 -0
  21. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/tests/test_bare_problem.py +0 -0
  22. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/tests/test_regression.py +0 -0
  23. {coco_experiment-2.8.1 → coco_experiment-2.8.3}/tests/test_suite.py +0 -0
@@ -64,3 +64,5 @@ test/regression-test/bbob_noisy_regression_test/data_legacy/*.json
64
64
  test/regression-test/bbob_noisy_regression_test/results
65
65
  build/c/.vscode
66
66
  bare_problem.c
67
+ test/regression-test/create/exdata
68
+ test/regression-test/exdata
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: coco-experiment
3
- Version: 2.8.1
3
+ Version: 2.8.3
4
4
  Summary: Benchmarking framework for all types of black-box optimization algorithms.
5
5
  Project-URL: Homepage, https://github.com/numbbo/coco-experiment
6
6
  Project-URL: Documentation, https://numbbo.github.io/coco-doc/apidocs/cocoex/
@@ -11,14 +11,13 @@ License-File: LICENSE
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: License :: OSI Approved :: BSD License
13
13
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.8
15
- Classifier: Programming Language :: Python :: 3.9
16
- Classifier: Programming Language :: Python :: 3.10
17
- Classifier: Programming Language :: Python :: 3.11
18
14
  Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Programming Language :: Python :: 3.15
19
18
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
- Requires-Python: >=3.8
21
- Requires-Dist: numpy>=1.24.0
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: numpy>=1.26.0
22
21
  Description-Content-Type: text/markdown
23
22
 
24
23
  <h1 align="center">
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["meson-python", "Cython >= 3.0.6", "wheel", "numpy"]
2
+ requires = ["meson-python >= 0.22", "Cython >= 3.3", "wheel", "numpy >= 2.5"]
3
3
  build-backend = 'mesonpy'
4
4
 
5
5
  [project]
@@ -22,20 +22,21 @@ authors = [
22
22
  ]
23
23
  description = 'Benchmarking framework for all types of black-box optimization algorithms.'
24
24
  readme = "README.md"
25
- requires-python = ">=3.8"
25
+ requires-python = ">=3.12"
26
26
  license = { text = "BSD-3-Clause" }
27
27
  classifiers = [
28
28
  "Development Status :: 4 - Beta",
29
29
  "License :: OSI Approved :: BSD License",
30
30
  "Programming Language :: Python",
31
- "Programming Language :: Python :: 3.8",
32
- "Programming Language :: Python :: 3.9",
33
- "Programming Language :: Python :: 3.10",
34
- "Programming Language :: Python :: 3.11",
35
31
  "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Programming Language :: Python :: 3.14",
34
+ "Programming Language :: Python :: 3.15",
36
35
  "Programming Language :: Python :: Implementation :: CPython",
37
36
  ]
38
- dependencies = ["numpy >= 1.24.0"]
37
+ dependencies = [
38
+ "numpy >= 1.26.0",
39
+ ]
39
40
  dynamic = ["version"]
40
41
 
41
42
  [project.urls]
@@ -48,7 +49,7 @@ where = ["src"]
48
49
 
49
50
  [tool.pytest]
50
51
  log_cli = true
51
- addopts = "--doctest-modules"
52
+ addopts = ["--doctest-modules"]
52
53
 
53
54
  [tool.cibuildwheel]
54
55
  build-frontend = "build"
@@ -71,3 +72,8 @@ include = [
71
72
 
72
73
  [tool.hatch.version]
73
74
  path = "src/cocoex/_version.py"
75
+
76
+ [dependency-groups]
77
+ dev = [
78
+ "build>=1.6",
79
+ ]
@@ -19,6 +19,7 @@ from . import noiser # noqa: F401
19
19
  from . import solvers # noqa: F401
20
20
  from . import utilities # noqa: F401
21
21
  from . import exceptions # noqa: F401
22
+ # from . import test # noqa: F401 # gives a circular import, why???
22
23
  from .interface import Observer as _Observer
23
24
  from .interface import Problem as _Problem
24
25
  from .interface import Suite as _Suite
@@ -1,7 +1,7 @@
1
1
  # file generated by fabricate
2
2
  # Do not change, do not track in version control!
3
3
 
4
- __version__ = "2.8.1"
4
+ __version__ = "2.8.3"
5
5
  version = __version__
6
6
 
7
7
  if __name__ == "__main__":
@@ -25922,6 +25922,18 @@ void coco_suite_decode_problem_index(const coco_suite_t *suite, const size_t pro
25922
25922
  #include <limits.h>
25923
25923
  #include <math.h>
25924
25924
 
25925
+ /**
25926
+ * @brief Number of triggers per decade of increasing evaluations (20), was: 20
25927
+ *
25928
+ * Changing this number currently breaks the test_logger_bbob.c unit-test
25929
+ */
25930
+ #define OBSERVER_DEFAULT_NUMBER_OF_EVALUATION_TRIGGERS 20
25931
+
25932
+ /**
25933
+ * @brief Number of triggers per decade of decreasing Df values (20), was: 5, then 100
25934
+ */
25935
+ #define OBSERVER_DEFAULT_NUMBER_OF_TARGET_TRIGGERS 20
25936
+
25925
25937
  /**
25926
25938
  * @brief The type for triggers based on logarithmic target values (targets that
25927
25939
  * are uniformly distributed in the logarithmic space).
@@ -26229,14 +26241,16 @@ static void coco_observer_targets_free(coco_observer_targets_t *targets) {
26229
26241
  * dim*1, dim*2, dim*5, 10*dim*1, 10*dim*2, 10*dim*5, 100*dim*1, 100*dim*2,
26230
26242
  * 100*dim*5, ...
26231
26243
  */
26232
- static coco_observer_evaluations_t *coco_observer_evaluations(const char *base_evaluations, const size_t dimension) {
26244
+ static coco_observer_evaluations_t *coco_observer_evaluations(const size_t number_evaluation_triggers,
26245
+ const char *base_evaluations,
26246
+ const size_t dimension) {
26233
26247
 
26234
26248
  coco_observer_evaluations_t *evaluations = (coco_observer_evaluations_t *)coco_allocate_memory(sizeof(*evaluations));
26235
26249
 
26236
26250
  /* First trigger */
26237
26251
  evaluations->value1 = 1;
26238
26252
  evaluations->exponent1 = 0;
26239
- evaluations->number_of_triggers = 20;
26253
+ evaluations->number_of_triggers = number_evaluation_triggers;
26240
26254
 
26241
26255
  /* Second trigger */
26242
26256
  evaluations->base_evaluations =
@@ -26369,6 +26383,12 @@ static coco_observer_t *coco_observer_allocate(
26369
26383
  observer->logger_free_function = NULL;
26370
26384
  observer->restart_function = NULL;
26371
26385
  observer->is_active = 1;
26386
+ coco_debug("Function coco_observer_allocate() called with values: result_folder: %s, observer_name: %s, algorithm_name: %s, "
26387
+ "algorithm_info: %s, settings: %s, number_target_triggers: %lu, log_target_precision: %e, lin_target_precision: %e, "
26388
+ "number_evaluation_triggers: %lu, base_evaluation_triggers: %s, precision_x: %d, precision_f: %d, precision_g: %d, "
26389
+ "log_discrete_as_int: %d", result_folder, observer_name, algorithm_name, algorithm_info, settings, (unsigned long)number_target_triggers,
26390
+ log_target_precision, lin_target_precision, (unsigned long)number_evaluation_triggers, base_evaluation_triggers, precision_x, precision_f,
26391
+ precision_g, log_discrete_as_int);
26372
26392
  return observer;
26373
26393
  }
26374
26394
 
@@ -26557,6 +26577,11 @@ static void observer_bbob(coco_observer_t *observer, const char *options, coco_o
26557
26577
  */
26558
26578
  #define LOGGER_BBOB_INFEASIBLE_PENALTY 1e10
26559
26579
 
26580
+ /**
26581
+ * Record variable values only when #variables is below this threshold, was: 22
26582
+ */
26583
+ #define LOGGER_BBOB_NUMBER_OF_VARIABLES_THRESHOLD 7
26584
+
26560
26585
  /**
26561
26586
  * @brief The bbob logger data type.
26562
26587
  */
@@ -26696,7 +26721,7 @@ static void logger_bbob_output(FILE *data_file, logger_bbob_data_t *logger, cons
26696
26721
  fprintf(data_file, "%+10.9e", best_value);
26697
26722
  }
26698
26723
 
26699
- if (logger->number_of_variables < 22) {
26724
+ if (logger->number_of_variables < LOGGER_BBOB_NUMBER_OF_VARIABLES_THRESHOLD) {
26700
26725
  for (i = 0; i < logger->number_of_variables; i++) {
26701
26726
  if ((i < logger->number_of_integer_variables) && (logger->log_discrete_as_int))
26702
26727
  fprintf(data_file, " %d", coco_double_to_int(x[i]));
@@ -27235,8 +27260,8 @@ static coco_problem_t *logger_bbob(coco_observer_t *observer, coco_problem_t *in
27235
27260
  /* Initialize triggers performance and evaluation triggers depending on the observer option */
27236
27261
  logger_data->targets = coco_observer_targets(suite->known_optima, observer->lin_target_precision,
27237
27262
  observer->number_target_triggers, observer->log_target_precision);
27238
- logger_data->evaluations =
27239
- coco_observer_evaluations(observer->base_evaluation_triggers, inner_problem->number_of_variables);
27263
+ logger_data->evaluations = coco_observer_evaluations(
27264
+ observer->number_evaluation_triggers, observer->base_evaluation_triggers, inner_problem->number_of_variables);
27240
27265
  logger_data->mdat_targets = coco_observer_targets(suite->known_optima, observer->lin_target_precision,
27241
27266
  observer->number_target_triggers, observer->log_target_precision);
27242
27267
 
@@ -27249,7 +27274,7 @@ static coco_problem_t *logger_bbob(coco_observer_t *observer, coco_problem_t *in
27249
27274
  observer_data->observed_problem = problem;
27250
27275
  return problem;
27251
27276
  }
27252
- #line 498 "coco_observer.c"
27277
+ #line 518 "coco_observer.c"
27253
27278
  #line 1 "logger_bbob_old.c"
27254
27279
  /**
27255
27280
  * @file logger_bbob_old.c
@@ -27902,8 +27927,8 @@ static coco_problem_t *logger_bbob_old(coco_observer_t *observer, coco_problem_t
27902
27927
 
27903
27928
  /* Initialize triggers based on target values and number of evaluations */
27904
27929
  logger_data->targets = coco_observer_log_targets(observer->number_target_triggers, observer->log_target_precision);
27905
- logger_data->evaluations =
27906
- coco_observer_evaluations(observer->base_evaluation_triggers, inner_problem->number_of_variables);
27930
+ logger_data->evaluations = coco_observer_evaluations(
27931
+ observer->number_evaluation_triggers, observer->base_evaluation_triggers, inner_problem->number_of_variables);
27907
27932
 
27908
27933
  problem =
27909
27934
  coco_problem_transformed_allocate(inner_problem, logger_data, logger_bbob_old_free, observer->observer_name);
@@ -27912,7 +27937,7 @@ static coco_problem_t *logger_bbob_old(coco_observer_t *observer, coco_problem_t
27912
27937
  bbob_old_logger_is_open = 1;
27913
27938
  return problem;
27914
27939
  }
27915
- #line 499 "coco_observer.c"
27940
+ #line 519 "coco_observer.c"
27916
27941
  #line 1 "logger_biobj.c"
27917
27942
  /**
27918
27943
  * @file logger_biobj.c
@@ -29599,7 +29624,8 @@ static logger_biobj_indicator_t *logger_biobj_indicator(const logger_biobj_data_
29599
29624
 
29600
29625
  indicator->targets = coco_observer_targets(suite->known_optima, observer->lin_target_precision,
29601
29626
  observer->number_target_triggers, observer->log_target_precision);
29602
- indicator->evaluations = coco_observer_evaluations(observer->base_evaluation_triggers, problem->number_of_variables);
29627
+ indicator->evaluations = coco_observer_evaluations(observer->number_evaluation_triggers, observer->base_evaluation_triggers,
29628
+ problem->number_of_variables);
29603
29629
 
29604
29630
  /* Prepare the info file */
29605
29631
  path_name = coco_allocate_string(COCO_PATH_MAX + 1);
@@ -30236,7 +30262,7 @@ static coco_problem_t *logger_biobj(coco_observer_t *observer, coco_problem_t *i
30236
30262
  observer_data->observed_problem = problem;
30237
30263
  return problem;
30238
30264
  }
30239
- #line 500 "coco_observer.c"
30265
+ #line 520 "coco_observer.c"
30240
30266
  #line 1 "logger_rw.c"
30241
30267
  /**
30242
30268
  * @file logger_rw.c
@@ -30572,7 +30598,7 @@ static coco_problem_t *logger_rw(coco_observer_t *observer, coco_problem_t *inne
30572
30598
 
30573
30599
  return problem;
30574
30600
  }
30575
- #line 501 "coco_observer.c"
30601
+ #line 521 "coco_observer.c"
30576
30602
  #line 1 "logger_toy.c"
30577
30603
  /**
30578
30604
  * @file logger_toy.c
@@ -30761,7 +30787,7 @@ static coco_problem_t *logger_toy(coco_observer_t *observer, coco_problem_t *inn
30761
30787
 
30762
30788
  return problem;
30763
30789
  }
30764
- #line 502 "coco_observer.c"
30790
+ #line 522 "coco_observer.c"
30765
30791
 
30766
30792
  /**
30767
30793
  * Currently, four observers are supported:
@@ -30905,13 +30931,13 @@ coco_observer_t *coco_observer(const char *observer_name, const char *observer_o
30905
30931
  strcpy(settings, "");
30906
30932
  }
30907
30933
 
30908
- number_target_triggers = 100;
30934
+ number_target_triggers = OBSERVER_DEFAULT_NUMBER_OF_TARGET_TRIGGERS;
30909
30935
  if (coco_options_read_size_t(observer_options, "number_target_triggers", &number_target_triggers) != 0) {
30910
30936
  if (number_target_triggers < 0) {
30911
30937
  coco_warning("coco_observer(): Unsuitable observer option value "
30912
30938
  "(number_target_triggers: %lu) ignored",
30913
30939
  number_target_triggers);
30914
- number_target_triggers = 100;
30940
+ number_target_triggers = OBSERVER_DEFAULT_NUMBER_OF_TARGET_TRIGGERS;
30915
30941
  }
30916
30942
  }
30917
30943
 
@@ -30935,13 +30961,13 @@ coco_observer_t *coco_observer(const char *observer_name, const char *observer_o
30935
30961
  }
30936
30962
  }
30937
30963
 
30938
- number_evaluation_triggers = 20;
30964
+ number_evaluation_triggers = OBSERVER_DEFAULT_NUMBER_OF_EVALUATION_TRIGGERS;
30939
30965
  if (coco_options_read_size_t(observer_options, "number_evaluation_triggers", &number_evaluation_triggers) != 0) {
30940
30966
  if (number_evaluation_triggers < 4) {
30941
30967
  coco_warning("coco_observer(): Unsuitable observer option value "
30942
30968
  "(number_evaluation_triggers: %lu) ignored",
30943
30969
  number_evaluation_triggers);
30944
- number_evaluation_triggers = 20;
30970
+ number_evaluation_triggers = OBSERVER_DEFAULT_NUMBER_OF_EVALUATION_TRIGGERS;
30945
30971
  }
30946
30972
  }
30947
30973
 
@@ -31527,7 +31553,7 @@ void coco_archive_free(coco_archive_t *archive) {
31527
31553
  * don't change, don't track in version control!
31528
31554
  */
31529
31555
 
31530
- const char *coco_version = "2.8.1";
31556
+ const char *coco_version = "2.8.3";
31531
31557
  #line 1 "coco_runtime_c.c"
31532
31558
  /**
31533
31559
  * @file coco_runtime_c.c
@@ -424,7 +424,7 @@ cdef class Suite:
424
424
  % (self.name, self.instance, self.options,
425
425
  len(self), '' if len(self) == 1 else 's',
426
426
  '' if len(self.dimensions) == 1 else 's',
427
- '%d=%d' % (min(self.dimensions), max(self.dimensions)))
427
+ '%d-%d' % (min(self.dimensions), max(self.dimensions)))
428
428
  def __len__(self):
429
429
  return len(self._indices)
430
430
 
@@ -52,11 +52,12 @@ class Noisifier:
52
52
  ### prepare
53
53
  suite = cocoex.Suite(suite_name, "", "")
54
54
  observer = cocoex.Observer(suite_name, "")
55
+ noisifier = cocoex.noiser.Noisifier() # wrapper without internal state
55
56
 
56
57
  ### go
57
58
  for problem in suite: # this loop may take several minutes or more
58
59
  problem.observe_with(observer) # generates the data for cocopp
59
- problem = cocoex.noiser.Noisifier().noisify(problem) # a Noisifier
60
+ problem = noisifier.noisify(problem) # wrap problem as noisy
60
61
  fmin(problem, problem.initial_solution, disp=False)
61
62
 
62
63
  The `problem` is now a `Noisifier` but it still abides by the interface
@@ -70,6 +71,24 @@ class Noisifier:
70
71
  noise generator and the numbers scaled by pi/2 such that P(number > k)
71
72
  equals about 1/k when k >= 5.
72
73
 
74
+ A minimal regression test:
75
+
76
+ >>> import cocoex
77
+ >>> def eq(x, y):
78
+ ... return [cocoex.utilities.about_equal(xi, yi)
79
+ ... for xi, yi in zip(x, y)]
80
+ >>> def fun(x):
81
+ ... return 2 * x[0], 3 * x[1]
82
+
83
+ >>> n = cocoex.noiser.Noisifier(p_add=.5)
84
+ >>> f = n.noisify(fun)
85
+ >>> assert all(eq(f([1, 2]), [2, 41.39010606165791])
86
+ ... ), f([1, 2])
87
+ >>> assert all(eq(f([2, 3, 4]), [11.518074565992698, 9.705537168513859])
88
+ ... ), f([2, 3, 4]) # x[2:] have no influence here
89
+ >>> assert all(eq(f([-1, 2]), [-2, 6])
90
+ ... ), f([-1, 2])
91
+
73
92
  See also https://github.com/numbbo/coco-experiment/issues/36 and
74
93
  https://github.com/numbbo/coco-experiment/blob/main/build/python/example/example_experiment_complete.py
75
94
 
@@ -269,7 +269,7 @@ class ProblemNonAnytime:
269
269
  ``p_unobserved.evaluations >= p_observed.evaluations``.
270
270
 
271
271
  """
272
- inherited_constant_attributes = [
272
+ inherited_constant_attributes = [ # easier and better solved by defining __getattr__!?
273
273
  'dimension',
274
274
  'id',
275
275
  'index',
@@ -308,13 +308,14 @@ class ProblemNonAnytime:
308
308
  The method records the delivered solution (if necessary) and
309
309
  prepares the problem to be run on the next budget by calling
310
310
  `reset`.
311
+
312
+ Whether the evaluation is done is based on the comparison with the best
313
+ so-far fvalue, which is a hack. When the behavior of the solver is known, it is better to use::
314
+
315
+ problem(x) # depending on whether this is necessary or not
316
+ problem.reset()
317
+
311
318
  """
312
- if self.evaluations < self.p_observed.evaluations:
313
- raise ValueError(
314
- "Delivered solutions should come from increasing budgets,\n"
315
- "however the current budget = {0} is smaller than the "
316
- "delivery budget = {1}".format(
317
- self.p_observed.evaluations, self.evaluations))
318
319
  # assuming that "same fitness" means the solution was already evaluated
319
320
  if self.p_unobserved(x, *args, **kwargs) != self.best_observed_fvalue1:
320
321
  # ideally we would decrease the observed evaluation counter,
@@ -376,7 +377,7 @@ class SameFunction:
376
377
  >>> from cocoex.utilities import SameFunction
377
378
  >>>
378
379
  >>> suite = cocoex.Suite('bbob', '', '')
379
- >>> already_seen = SameFunction()
380
+ >>> already_seen = seen = SameFunction()
380
381
  >>> processed = 0
381
382
  >>> for problem in suite:
382
383
  ... if already_seen(problem.id) > 5:
File without changes