fcmaes 1.1.3__py3-none-any.whl → 1.6.9__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.
fcmaes/astro.py CHANGED
@@ -6,38 +6,37 @@
6
6
  import sys
7
7
  import math
8
8
  import os
9
- import numpy as np
10
9
  import ctypes as ct
11
10
  from scipy.optimize import Bounds
11
+ from fcmaes.decpp import libcmalib
12
12
 
13
- basepath = os.path.dirname(os.path.abspath(__file__))
14
- if sys.platform.startswith('linux'):
15
- libgtoplib = ct.cdll.LoadLibrary(basepath + '/lib/libgtoplib.so')
16
- elif 'mac' in sys.platform:
17
- libgtoplib = ct.cdll.LoadLibrary(basepath + '/lib/libgtoplib.dylib')
18
- else:
19
- libgtoplib = ct.cdll.LoadLibrary(basepath + '/lib/libgtoplib.dll')
13
+ if not libcmalib is None:
14
+
15
+ astro_map = {
16
+ "messengerfullC": libcmalib.messengerfullC,
17
+ "messengerC": libcmalib.messengerC,
18
+ "gtoc1C": libcmalib.gtoc1C,
19
+ "cassini1C": libcmalib.cassini1C,
20
+ "cassini1minlpC": libcmalib.cassini1minlpC,
21
+ "cassini2C": libcmalib.cassini2C,
22
+ "rosettaC": libcmalib.rosettaC,
23
+ "sagasC": libcmalib.sagasC,
24
+ "tandemC": libcmalib.tandemC,
25
+ "tandemCu": libcmalib.tandemCu,
26
+ "cassini2minlpC": libcmalib.cassini2minlpC,
27
+ }
20
28
 
29
+ freemem = libcmalib.free_mem
30
+ freemem.argtypes = [ct.POINTER(ct.c_double)]
31
+
21
32
  class Astrofun(object):
22
33
  """Provides access to ESAs GTOP optimization test functions."""
23
34
  def __init__(self, name, fun_c, lower, upper):
24
35
  self.name = name
36
+ self.fun_c = fun_c
25
37
  self.bounds = Bounds(lower, upper)
26
38
  self.fun = python_fun(fun_c, self.bounds)
27
39
 
28
- # for windows compatibility. Linux can pickle c pointers, windows can not
29
- astro_map = {
30
- "messengerfullC": libgtoplib.messengerfullC,
31
- "messengerC": libgtoplib.messengerC,
32
- "gtoc1C": libgtoplib.gtoc1C,
33
- "cassini1C": libgtoplib.cassini1C,
34
- "cassini2C": libgtoplib.cassini2C,
35
- "rosettaC": libgtoplib.rosettaC,
36
- "sagasC": libgtoplib.sagasC,
37
- "tandemC": libgtoplib.tandemC,
38
- "tandemCu": libgtoplib.tandemCu
39
- }
40
-
41
40
  for func in astro_map:
42
41
  astro_map[func].argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
43
42
  astro_map[func].restype = ct.c_double
@@ -66,7 +65,12 @@ class Gtoc1(object):
66
65
  Astrofun.__init__(self, 'GTOC1', "gtoc1C",
67
66
  [3000.,14.,14.,14.,14.,100.,366.,300.],
68
67
  [10000.,2000.,2000.,2000.,2000.,9000.,9000.,9000.]
69
- )
68
+ )
69
+ self.gfun = self.fun
70
+ self.fun = self.gtoc1
71
+
72
+ def gtoc1(self, x):
73
+ return self.gfun(x) - 2000000
70
74
 
71
75
  class Cassini1(object):
72
76
  """ see https://www.esa.int/gsp/ACT/projects/gtop/cassini1/ """
@@ -108,7 +112,7 @@ class Tandem(object):
108
112
  """ see https://www.esa.int/gsp/ACT/projects/gtop/tandem/ """
109
113
  def __init__(self, i, constrained=True):
110
114
  self.name = ('Tandem ' if constrained else 'Tandem unconstrained ') + str(i+1)
111
- self.cfun = "tandemC" if constrained else "tandemCu"
115
+ self.fun_c = "tandemC" if constrained else "tandemCu"
112
116
  self.fun = self.tandem
113
117
  self.bounds = Bounds([5475, 2.5, 0, 0, 20, 20, 20, 20, 0.01, 0.01, 0.01, 0.01, 1.05, 1.05, 1.05, -math.pi, -math.pi, -math.pi],
114
118
  [9132, 4.9, 1, 1, 2500, 2500, 2500, 2500, 0.99, 0.99, 0.99, 0.99, 10, 10, 10, math.pi, math.pi, math.pi])
@@ -123,17 +127,128 @@ class Tandem(object):
123
127
  n = len(x)
124
128
  array_type = ct.c_double * n
125
129
  ints_type = ct.c_int * 5
126
- fun_c = astro_map[self.cfun]
130
+ fun_c = astro_map[self.fun_c]
127
131
  fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double), ct.POINTER(ct.c_int)]
128
132
  try: # function is only defined inside bounds
129
- x = np.asarray(x).clip(self.bounds.lb, self.bounds.ub)
133
+ #x = np.asarray(x).clip(self.bounds.lb, self.bounds.ub)
130
134
  val = fun_c(n, array_type(*x), ints_type(*self.seq))
131
135
  if not math.isfinite(val):
132
136
  val = 1E10
133
137
  except Exception as ex:
134
138
  val = 1E10
135
139
  return val
136
-
140
+
141
+ class Tandem_minlp(object):
142
+ """ see https://www.esa.int/gsp/ACT/projects/gtop/tandem/ """
143
+ def __init__(self, constrained=True):
144
+ self.name = ('Tandem minlp ' if constrained else 'Tandem unconstrained minlp ')
145
+ self.fun_c = "tandemC" if constrained else "tandemCu"
146
+ self.fun = self.tandem_minlp
147
+ self.bounds = Bounds([5475, 2.5, 0, 0, 20, 20, 20, 20, 0.01, 0.01, 0.01, 0.01, 1.05, 1.05, 1.05, -math.pi, -math.pi, -math.pi,
148
+ 1.51,1.51,1.51],
149
+ [9132, 4.9, 1, 1, 2500, 2500, 2500, 2500, 0.99, 0.99, 0.99, 0.99, 10, 10, 10, math.pi, math.pi, math.pi,
150
+ 3.49,4.49,5.49])
151
+
152
+ def tandem_minlp(self, xs):
153
+ n = len(xs) - 3
154
+ x = xs[:-3]
155
+ seq = [3] + [int(round(xi)) for xi in xs[-3:]] + [6]
156
+ array_type = ct.c_double * n
157
+ ints_type = ct.c_int * 5
158
+ fun_c = astro_map[self.fun_c]
159
+ fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double), ct.POINTER(ct.c_int)]
160
+ try:
161
+ val = fun_c(n, array_type(*x), ints_type(*seq))
162
+ if not math.isfinite(val):
163
+ val = 1E10
164
+ except Exception as ex:
165
+ val = 1E10
166
+ return val
167
+
168
+ class Cassini1multi(object):
169
+ """ see https://www.esa.int/gsp/ACT/projects/gtop/cassini1/ """
170
+
171
+ def __init__(self, weights = [1,0,0,0], planets = [2,2,3,5]):
172
+ Astrofun.__init__(self, 'Cassini1minlp', "Cassini1minlpC",
173
+ [-1000.,30.,100.,30.,400.,1000.],
174
+ [0.,400.,470.,400.,2000.,6000.]
175
+ )
176
+ self.fun = self.cassini1
177
+ self.weights = weights
178
+ self.planets = planets
179
+ self.mfun = lambda x: cassini1multi(x + [2,2,3,5])
180
+
181
+ def cassini1(self, x):
182
+ r = cassini1multi(x + self.planets)
183
+ return self.weights[0]*r[0] + self.weights[1]*r[1] + self.weights[2]*r[2] + self.weights[3]*r[3]
184
+
185
+ class Cassini1minlp(object):
186
+ """ see https://www.esa.int/gsp/ACT/projects/gtop/cassini1/ """
187
+
188
+ def __init__(self, planets = [2,2,3,5]):
189
+ Astrofun.__init__(self, 'Cassini1', "cassini1C",
190
+ [-1000.,30.,100.,30.,400.,1000.],
191
+ [0.,400.,470.,400.,2000.,6000.]
192
+ )
193
+ self.fun = self.cassini1
194
+ self.planets = planets
195
+
196
+ def cassini1(self, x):
197
+ return cassini1minlp(list(x) + self.planets)
198
+
199
+ def cassini1minlp(x):
200
+ n = len(x)
201
+ array_type = ct.c_double * n
202
+ fun_c = astro_map["cassini1minlpC"]
203
+ fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
204
+ fun_c.restype = ct.POINTER(ct.c_double)
205
+ try: # function is only defined inside bounds
206
+ res = fun_c(n, array_type(*x))
207
+ dv = res[0]
208
+ freemem(res)
209
+ if not math.isfinite(dv):
210
+ dv = 1E10
211
+ except Exception as ex:
212
+ print(ex)
213
+ dv = 1E10
214
+ return dv
215
+
216
+ def cassini1multi(x):
217
+ n = len(x)
218
+ array_type = ct.c_double * n
219
+ fun_c = astro_map["cassini1minlpC"]
220
+ fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
221
+ fun_c.restype = ct.POINTER(ct.c_double)
222
+ try: # function is only defined inside bounds
223
+ res = fun_c(n, array_type(*x))
224
+ dv = res[0]
225
+ launch_dv = res[1]
226
+ freemem(res)
227
+ if not math.isfinite(dv):
228
+ dv = 1E10
229
+ except Exception as ex:
230
+ print(ex)
231
+ dv = 1E10
232
+ launch_dv = 1E10
233
+ tof = sum(x[1:6])
234
+ launch_time = x[0]
235
+ return [dv, tof, launch_time]
236
+
237
+ def cassini2multi(x):
238
+ n = len(x)
239
+ array_type = ct.c_double * n
240
+ fun_c = astro_map["cassini2minlpC"]
241
+ fun_c.argtypes = [ct.c_int, ct.POINTER(ct.c_double)]
242
+ fun_c.restype = ct.c_double
243
+ try: # function is only defined inside bounds
244
+ dv = fun_c(n, array_type(*x))
245
+ except Exception as ex:
246
+ print(ex)
247
+ dv = 1E99
248
+ tof = sum(x[4:9])
249
+ launch_time = x[0]
250
+ return [dv, tof, launch_time]
251
+
137
252
  class python_fun(object):
138
253
 
139
254
  def __init__(self, cfun, bounds):
@@ -151,4 +266,5 @@ class python_fun(object):
151
266
  val = 1E10
152
267
  except Exception as ex:
153
268
  val = 1E10
154
- return val
269
+ return val
270
+
fcmaes/bitecpp.py ADDED
@@ -0,0 +1,107 @@
1
+ # Copyright (c) Dietmar Wolz.
2
+ #
3
+ # This source code is licensed under the MIT license found in the
4
+ # LICENSE file in the root directory.
5
+
6
+ """ Implements a stochastic non-linear
7
+ bound-constrained derivative-free optimization method.
8
+ Description is available at https://github.com/avaneev/biteopt
9
+ """
10
+
11
+ import sys
12
+ import os
13
+ import math
14
+ import ctypes as ct
15
+ import numpy as np
16
+ from numpy.random import PCG64DXSM, Generator
17
+ from scipy.optimize import OptimizeResult, Bounds
18
+ from fcmaes.evaluator import _check_bounds, mo_call_back_type, callback_so, libcmalib
19
+
20
+ from typing import Optional, Callable
21
+ from numpy.typing import ArrayLike
22
+
23
+ os.environ['MKL_DEBUG_CPU_TYPE'] = '5'
24
+
25
+ def minimize(fun: Callable[[ArrayLike], float],
26
+ bounds: Optional[Bounds] = None,
27
+ x0: Optional[ArrayLike] = None,
28
+ max_evaluations: Optional[int] = 100000,
29
+ stop_fitness: Optional[float] = -np.inf,
30
+ M: Optional[int] = 1,
31
+ popsize: Optional[int] = 0,
32
+ stall_criterion: Optional[int] = 0,
33
+ rg: Optional[Generator] = Generator(PCG64DXSM()),
34
+ runid: Optional[int] = 0) -> OptimizeResult:
35
+ """Minimization of a scalar function of one or more variables using a
36
+ C++ SCMA implementation called via ctypes.
37
+
38
+ Parameters
39
+ ----------
40
+ fun : callable
41
+ The objective function to be minimized.
42
+ ``fun(x) -> float``
43
+ where ``x`` is an 1-D array with shape (dim,)
44
+ bounds : sequence or `Bounds`, optional
45
+ Bounds on variables. There are two ways to specify the bounds:
46
+ 1. Instance of the `scipy.Bounds` class.
47
+ 2. Sequence of ``(min, max)`` pairs for each element in `x`. None
48
+ is used to specify no bound.
49
+ x0 : ndarray, shape (dim,)
50
+ Initial guess. Array of real elements of size (dim,),
51
+ where 'dim' is the number of independent variables.
52
+ max_evaluations : int, optional
53
+ Forced termination after ``max_evaluations`` function evaluations.
54
+ stop_fitness : float, optional
55
+ Limit for fitness value. If reached minimize terminates.
56
+ M : int, optional
57
+ Depth to use, 1 for plain CBiteOpt algorithm, >1 for CBiteOptDeep. Expected range is [1; 36].
58
+ popsize = int, optional
59
+ initial population size.
60
+ stall_criterion : int, optional
61
+ Terminate if stall_criterion*128*evaluations stalled, Not used if <= 0
62
+ rg = numpy.random.Generator, optional
63
+ Random generator for creating random guesses.
64
+ runid : int, optional
65
+ id used to identify the run for debugging / logging.
66
+
67
+ Returns
68
+ -------
69
+ res : scipy.OptimizeResult
70
+ The optimization result is represented as an ``OptimizeResult`` object.
71
+ Important attributes are: ``x`` the solution array,
72
+ ``fun`` the best function value,
73
+ ``nfev`` the number of function evaluations,
74
+ ``nit`` the number of CMA-ES iterations,
75
+ ``status`` the stopping critera and
76
+ ``success`` a Boolean flag indicating if the optimizer exited successfully. """
77
+
78
+ lower, upper, guess = _check_bounds(bounds, x0, rg)
79
+ dim = guess.size
80
+ array_type = ct.c_double * dim
81
+ c_callback = mo_call_back_type(callback_so(fun, dim))
82
+ res = np.empty(dim+4)
83
+ res_p = res.ctypes.data_as(ct.POINTER(ct.c_double))
84
+ try:
85
+ optimizeBite_C(runid, c_callback, dim, int(rg.uniform(0, 2**32 - 1)),
86
+ None if x0 is None else array_type(*guess),
87
+ None if lower is None else array_type(*lower),
88
+ None if upper is None else array_type(*upper),
89
+ max_evaluations, stop_fitness, M, popsize, stall_criterion, res_p)
90
+ x = res[:dim]
91
+ val = res[dim]
92
+ evals = int(res[dim+1])
93
+ iterations = int(res[dim+2])
94
+ stop = int(res[dim+3])
95
+ return OptimizeResult(x=x, fun=val, nfev=evals, nit=iterations, status=stop, success=True)
96
+ except Exception as ex:
97
+ return OptimizeResult(x=None, fun=sys.float_info.max, nfev=0, nit=0, status=-1, success=False)
98
+
99
+ if not libcmalib is None:
100
+
101
+ optimizeBite_C = libcmalib.optimizeBite_C
102
+ optimizeBite_C.argtypes = [ct.c_long, mo_call_back_type, ct.c_int, ct.c_int, \
103
+ ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), ct.POINTER(ct.c_double), \
104
+ ct.c_int, ct.c_double, ct.c_int, ct.c_int, ct.c_int, ct.POINTER(ct.c_double)]
105
+
106
+
107
+