• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

WassimTenachi / PhySO / #16

28 Jul 2025 07:07AM UTC coverage: 70.145% (-10.8%) from 80.984%
#16

push

coveralls-python

WassimTenachi
fix

5963 of 8501 relevant lines covered (70.14%)

0.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.89
/physo/physym/tests/batch_UnitTest.py
1
import time
1✔
2
import unittest
1✔
3
import numpy as np
1✔
4
import torch
1✔
5

6
# Internal imports
7
from physo.physym import batch
1✔
8
from physo.physym.functions import data_conversion
1✔
9
from physo.physym import reward
1✔
10

11
class BatchTest(unittest.TestCase):
1✔
12

13

14
    def test_creation(self):
1✔
15

16
        # ------- TEST CASE -------
17
        DEVICE = 'cpu'
1✔
18
        if torch.cuda.is_available():
1✔
19
            DEVICE = 'cuda'
×
20

21
        # --- DATA ---
22
        N = int(1e6)
1✔
23
        x = data_conversion  (np.linspace(0.04, 4, N)  ).to(DEVICE)
1✔
24
        v = data_conversion  (np.linspace(0.10, 10, N) ).to(DEVICE)
1✔
25
        t = data_conversion  (np.linspace(0.06, 6, N)  ).to(DEVICE)
1✔
26
        X = torch.stack((x, v, t), axis=0)
1✔
27
        y = data_conversion(np.linspace(0.06, 6, N)).to(DEVICE)
1✔
28
        M  = data_conversion (1e6).to(DEVICE)
1✔
29
        c  = data_conversion (3e8).to(DEVICE)
1✔
30
        pi = data_conversion (np.pi).to(DEVICE)
1✔
31
        const1 = data_conversion (1.).to(DEVICE)
1✔
32

33
        # --- LIBRARY CONFIG ---
34
        args_make_tokens = {
1✔
35
                        # operations
36
                        "op_names"             : ["mul", "add", "neg", "inv", "cos"],
37
                        "use_protected_ops"    : True,
38
                        # input variables
39
                        "input_var_ids"        : {"x" : 0         , "v" : 1          , "t" : 2,        },
40
                        "input_var_units"      : {"x" : [1, 0, 0] , "v" : [1, -1, 0] , "t" : [0, 1, 0] },
41
                        "input_var_complexity" : {"x" : 0.        , "v" : 1.         , "t" : 0.,       },
42
                        # constants
43
                        "constants"            : {"pi" : pi        , "c" : c         , "M" : M         , "const1" : const1    },
44
                        "constants_units"      : {"pi" : [0, 0, 0] , "c" : [1, -1, 0], "M" : [0, 0, 1] , "const1" : [0, 0, 0] },
45
                        "constants_complexity" : {"pi" : 0.        , "c" : 0.        , "M" : 1.        , "const1" : 1.        },
46
                            }
47
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
48
                        "superparent_units" : [1, -2, 1],
49
                        "superparent_name"  : "y",
50
                        }
51

52
        # --- PRIORS ---
53
        priors_config  = [ ("UniformArityPrior", None),
1✔
54
                           ("HardLengthPrior", {"min_length": 1,
55
                                               "max_length": 8, }),]
56

57
        # --- BATCH ---
58
        batch_size    = 1000
1✔
59
        max_time_step = 30
1✔
60

61
        multi_X = [X,]
1✔
62
        multi_y = [y,]
1✔
63

64
        my_batch = batch.Batch(library_args     = library_args,
1✔
65
                               priors_config    = priors_config,
66
                               batch_size       = batch_size,
67
                               max_time_step    = max_time_step,
68
                               rewards_computer = reward.make_RewardsComputer (reward_function = reward.SquashedNRMSE),
69
                               multi_X = multi_X,
70
                               multi_y = multi_y,
71
                               )
72
        return None
1✔
73

74

75
    def test_dummy_epoch(self):
1✔
76

77
        # ------- TEST CASE -------
78
        DEVICE = 'cpu'
1✔
79
        if torch.cuda.is_available():
1✔
80
            DEVICE = 'cuda'
×
81

82
        # --- DATA ---
83
        N = int(1e3)
1✔
84
        x_array = np.linspace(0.04, 4, N)
1✔
85
        x = data_conversion (x_array).to(DEVICE)
1✔
86
        X = torch.stack((x,), axis=0)
1✔
87
        pi = data_conversion (np.pi).to(DEVICE)
1✔
88
        const1 = data_conversion (1.).to(DEVICE)
1✔
89
        T_array  = 1.028
1✔
90
        v0_array = 0.995
1✔
91
        T = data_conversion (T_array).to(DEVICE)
1✔
92
        v0 = data_conversion (v0_array).to(DEVICE)
1✔
93
        y_target = data_conversion(x_array/T_array + v0_array).to(DEVICE)
1✔
94

95
        # --- LIBRARY CONFIG ---
96
        args_make_tokens = {
1✔
97
                        # operations
98
                        "op_names"             : ["add", "div"],
99
                        "use_protected_ops"    : True,
100
                        # input variables
101
                        "input_var_ids"        : {"x" : 0         },
102
                        "input_var_units"      : {"x" : [1, 0, 0] },
103
                        "input_var_complexity" : {"x" : 1.        },
104
                        # constants
105
                        "constants"            : {"pi" : pi        , "const1" : const1    , "T" : T         , "v0" : v0         },
106
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] , "T" : [0, 1, 0] , "v0" : [1, -1, 0] },
107
                        "constants_complexity" : {"pi" : 1.        , "const1" : 1.        , "T" : 1.        , "v0" : 1.         },
108
                            }
109
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
110
                        "superparent_units" : [1, -1, 0],
111
                        "superparent_name"  : "v",
112
                        }
113

114
        # --- PRIORS ---
115
        priors_config  = [ ("UniformArityPrior", None),
1✔
116
                           ("HardLengthPrior", {"min_length": 1,
117
                                               "max_length": 5, }),
118
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
119

120
        # --- BATCH ---
121
        batch_size    = 1000
1✔
122
        max_time_step = 10
1✔
123

124
        multi_X = [X,]
1✔
125
        multi_y = [y_target,]
1✔
126

127
        my_batch = batch.Batch(library_args     = library_args,
1✔
128
                               priors_config    = priors_config,
129
                               batch_size       = batch_size,
130
                               max_time_step    = max_time_step,
131
                               rewards_computer = reward.make_RewardsComputer (reward_function = reward.SquashedNRMSE),
132
                               multi_X = multi_X,
133
                               multi_y = multi_y,
134
                               )
135

136
        # --- DUMMY EPOCH ---
137
        t0 = time.perf_counter()
1✔
138
        for step in range(max_time_step):
1✔
139
            # Embedding output
140
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
1✔
141
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
1✔
142
            # Dummy model output
143
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
1✔
144
            # Actions
145
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
1✔
146
            actions      = actions.cpu().numpy()
1✔
147
            my_batch.programs.append(actions)
×
148
        # Embedding output
149
        lengths = my_batch.programs.n_lengths
1✔
150
        R       = my_batch.get_rewards()
×
151
        # Computing model loss using (probs,actions, R, lengths)
152
        # ...
153
        t1 = time.perf_counter()
1✔
154
        print("Dummy epoch time = %f ms"%((t1-t0)*1e3))
×
155

156
    def test_dummy_epoch_duplicate_elimination (self):
×
157

158
        # ------- TEST CASE -------
159
        DEVICE = 'cpu'
1✔
160
        if torch.cuda.is_available():
×
161
            DEVICE = 'cuda'
×
162

163
        # --- DATA ---
164
        N = int(1e3)
1✔
165
        x_array = np.linspace(0.04, 4, N)
1✔
166
        x = data_conversion (x_array).to(DEVICE)
1✔
167
        X = torch.stack((x,), axis=0)
1✔
168
        pi = data_conversion (np.pi).to(DEVICE)
1✔
169
        const1 = data_conversion (1.).to(DEVICE)
1✔
170
        T_array  = 1.028
1✔
171
        v0_array = 0.995
1✔
172
        T = data_conversion (T_array).to(DEVICE)
1✔
173
        v0 = data_conversion (v0_array).to(DEVICE)
1✔
174
        y_target = data_conversion(x_array/T_array + v0_array).to(DEVICE)
×
175

176
        # --- LIBRARY CONFIG ---
177
        args_make_tokens = {
1✔
178
                        # operations
179
                        "op_names"             : ["add", "div"],
180
                        "use_protected_ops"    : True,
181
                        # input variables
182
                        "input_var_ids"        : {"x" : 0         },
183
                        "input_var_units"      : {"x" : [1, 0, 0] },
184
                        "input_var_complexity" : {"x" : 1.        },
185
                        # constants
186
                        "constants"            : {"pi" : pi        , "const1" : const1    , "T" : T         , "v0" : v0         },
187
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] , "T" : [0, 1, 0] , "v0" : [1, -1, 0] },
188
                        "constants_complexity" : {"pi" : 1.        , "const1" : 1.        , "T" : 1.        , "v0" : 1.         },
189
                            }
190
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
191
                        "superparent_units" : [1, -1, 0],
192
                        "superparent_name"  : "v",
193
                        }
194

195
        # --- PRIORS ---
196
        priors_config  = [ ("UniformArityPrior", None),
1✔
197
                           ("HardLengthPrior", {"min_length": 1,
198
                                               "max_length": 5, }),
199
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
200

201
        # --- BATCH ---
202
        batch_size    = 1000
1✔
203
        max_time_step = 10
×
204

205
        multi_X = [X,]
1✔
206
        multi_y = [y_target,]
×
207

208
        my_batch = batch.Batch(library_args     = library_args,
1✔
209
                               priors_config    = priors_config,
210
                               batch_size       = batch_size,
211
                               max_time_step    = max_time_step,
212
                               rewards_computer = reward.make_RewardsComputer (reward_function = reward.SquashedNRMSE,
213
                                                                               zero_out_unphysical = True,
214
                                                                               zero_out_duplicates = True),
215
                               multi_X = multi_X,
216
                               multi_y = multi_y,
217
                               )
218

219
        # --- DUMMY EPOCH ---
220
        t0 = time.perf_counter()
1✔
221
        for step in range(max_time_step):
×
222
            # Embedding output
223
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
1✔
224
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
×
225
            # Dummy model output
226
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
×
227
            # Actions
228
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
1✔
229
            actions      = actions.cpu().numpy()
×
230
            my_batch.programs.append(actions)
1✔
231
        # Embedding output
232
        lengths = my_batch.programs.n_lengths
×
233
        R       = my_batch.get_rewards()
×
234
        # Computing model loss using (probs,actions, R, lengths)
235
        # ...
236
        t1 = time.perf_counter()
1✔
237
        eps = 1e-5
1✔
238
        n_solutions = (np.abs(1-R) < eps).sum()
1✔
239
        n_kept = (R>0).sum()
1✔
240
        print("Dummy epoch time (w duplicate elimination) = %f ms (found %i/%i candidates with R > 0 "
1✔
241
              "and %i/%i with R = 1 +/- %f)"%((t1-t0)*1e3, n_kept, batch_size, n_solutions, batch_size, eps))
242

243
    def test_dummy_epoch_free_consts(self):
×
244

245
        # ------- TEST CASE -------
246
        DEVICE = 'cpu'
×
247
        if torch.cuda.is_available():
×
248
            DEVICE = 'cuda'
×
249

250
        # --- DATA ---
251
        N = int(1e3)
1✔
252
        x_array = np.linspace(0.04, 4, N)
1✔
253
        x = data_conversion (x_array).to(DEVICE)
1✔
254
        X = torch.stack((x,), axis=0)
1✔
255
        pi = data_conversion (np.pi).to(DEVICE)
1✔
256
        const1 = data_conversion (1.).to(DEVICE)
1✔
257
        T = 1.028
1✔
258
        v0 = 0.995
×
259
        y_target = data_conversion(x_array/T + v0).to(DEVICE)
×
260

261

262
        # --- LIBRARY CONFIG ---
263
        args_make_tokens = {
1✔
264
                        # operations
265
                        "op_names"             : ["add", "div"],
266
                        "use_protected_ops"    : True,
267
                        # input variables
268
                        "input_var_ids"        : {"x" : 0         },
269
                        "input_var_units"      : {"x" : [1, 0, 0] },
270
                        "input_var_complexity" : {"x" : 0.        },
271
                        # constants
272
                        "constants"            : {"pi" : pi        , "const1" : const1    },
273
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] },
274
                        "constants_complexity" : {"pi" : 0.        , "const1" : 1.        },
275
                        # free constants
276
                        "free_constants"            : {"T"              , "v0"              ,},
277
                        "free_constants_init_val"   : {"T" : 1.         , "v0" : 1.         ,},
278
                        "free_constants_units"      : {"T" : [0, 1, 0] , "v0" : [1, -1, 0] ,},
279
                        "free_constants_complexity" : {"T" : 0.         , "v0" : 0.         ,},
280
                            }
281
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
282
                        "superparent_units" : [1, -1, 0],
283
                        "superparent_name"  : "v",
284
                        }
285

286
        # --- PRIORS ---
287
        priors_config  = [ ("UniformArityPrior", None),
1✔
288
                           ("HardLengthPrior", {"min_length": 1,
289
                                               "max_length": 5, }),
290
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
291

292
        # --- FREE CONST OPTI ---
293
        free_const_opti_args = {
1✔
294
            'loss'   : "MSE",
295
            'method' : 'LBFGS',
296
            'method_args': {
297
                        'n_steps' : 30,
298
                        'tol'     : 1e-6,
299
                        'lbfgs_func_args' : {
300
                            'max_iter'       : 4,
301
                            'line_search_fn' : "strong_wolfe",
302
                                             },
303
                            },
304
        }
305

306
        # --- BATCH ---
307
        batch_size    = 1000
×
308
        max_time_step = 10
1✔
309

310
        multi_X = [X,]
×
311
        multi_y = [y_target,]
1✔
312

313
        my_batch = batch.Batch(library_args     = library_args,
1✔
314
                               priors_config    = priors_config,
315
                               batch_size       = batch_size,
316
                               max_time_step    = max_time_step,
317
                               rewards_computer = reward.make_RewardsComputer (reward_function     = reward.SquashedNRMSE,
318
                                                                               zero_out_unphysical = True),
319
                               free_const_opti_args = free_const_opti_args,
320
                               multi_X = multi_X,
321
                               multi_y = multi_y,
322
                               )
323

324
        # --- DUMMY EPOCH ---
325
        t0 = time.perf_counter()
×
326
        for step in range(max_time_step):
1✔
327
            # Embedding output
328
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
×
329
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
1✔
330
            # Dummy model output
331
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
1✔
332
            # Actions
333
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
×
334
            actions      = actions.cpu().numpy()
1✔
335
            my_batch.programs.append(actions)
1✔
336
        # Embedding output
337
        lengths = my_batch.programs.n_lengths
×
338
        R       = my_batch.get_rewards()
1✔
339
        # Computing model loss using (probs,actions, R, lengths)
340
        # ...
341
        t1 = time.perf_counter()
1✔
342
        eps = 1e-5
×
343
        n_solutions = (np.abs(1-R) < eps).sum()
1✔
344
        print("Dummy epoch time (w free const) = %f ms (found %i/%i candidates with R = 1 +/- %f)"%((t1-t0)*1e3, n_solutions, batch_size, eps))
×
345

346
    def test_dummy_epoch_spe_free_consts_mdho2d(self):
×
347

348
        DEVICE = 'cpu'
×
349
        #if torch.cuda.is_available():
350
        #    DEVICE = 'cuda'
351

352
        # -------------------------------------- Making fake datasets --------------------------------------
353

354
        multi_X = []
1✔
355
        for n_samples in [90, 100, 110]:
1✔
356
            x1 = np.linspace(0, 10, n_samples)
1✔
357
            x2 = np.linspace(0, 1 , n_samples)
1✔
358
            X = np.stack((x1,x2),axis=0)
1✔
359
            X = torch.tensor(X).to(DEVICE)
×
360
            multi_X.append(X)
1✔
361
        multi_X = multi_X*10                         # (n_realizations,) of (n_dim, [n_samples depends on dataset],)
1✔
362

363
        n_samples_per_dataset = np.array([X.shape[1] for X in multi_X])
1✔
364
        n_all_samples = n_samples_per_dataset.sum()
×
365
        n_realizations = len(multi_X)
×
366
        def flatten_multi_data (multi_data,):
×
367
            """
368
            Flattens multiple datasets into a single one for vectorized evaluation.
369
            Parameters
370
            ----------
371
            multi_data : list of length (n_realizations,) of torch.tensor of shape (..., [n_samples depends on dataset],)
372
                List of datasets to be flattened.
373
            Returns
374
            -------
375
            torch.tensor of shape (..., n_all_samples)
376
                Flattened data (n_all_samples = sum([n_samples depends on dataset])).
377
            """
378
            flattened_data = torch.cat(multi_data, axis=-1) # (..., n_all_samples)
1✔
379
            return flattened_data
×
380

381
        def unflatten_multi_data (flattened_data):
×
382
            """
383
            Unflattens a single data into multiple ones.
384
            Parameters
385
            ----------
386
            flattened_data : torch.tensor of shape (..., n_all_samples)
387
                Flattened data (n_all_samples = sum([n_samples depends on dataset])).
388
            Returns
389
            -------
390
            list of len (n_realizations,) of torch.tensor of shape (..., [n_samples depends on dataset],)
391
                Unflattened data.
392
            """
393
            return list(torch.split(flattened_data, n_samples_per_dataset.tolist(), dim=-1)) # (n_realizations,) of (..., [n_samples depends on dataset],)
1✔
394

395
        #y_weights_per_dataset = np.array([0, 0.001, 1.0]*10) # Shows weights work
396
        y_weights_per_dataset = np.array([1., 1., 1.]*10)
1✔
397
        multi_y_weights = [np.full(shape=(n_samples_per_dataset[i],), fill_value=y_weights_per_dataset[i]) for i in range (n_realizations)]
×
398
        multi_y_weights = [torch.tensor(y_weights).to(DEVICE) for y_weights in multi_y_weights]
1✔
399
        y_weights_flatten = flatten_multi_data(multi_y_weights)
×
400

401
        multi_X_flatten = flatten_multi_data(multi_X)  # (n_dim, n_all_samples)
×
402

403
        # Making fake ideal parameters
404
        # n_spe_params   = 3
405
        # n_class_params = 2
406
        random_shift       = (np.random.rand(n_realizations,3)-0.5)*0.8
1✔
407
        ideal_spe_params   = torch.tensor(np.array([1.123, 0.345, 0.116]) + random_shift) # (n_realizations, n_spe_params,)
×
408
        ideal_spe_params   = ideal_spe_params.transpose(0,1)                              # (n_spe_params, n_realizations)
1✔
409
        ideal_class_params = torch.tensor(np.array([1.389, 1.005]))                       # (n_class_params, )
1✔
410

411
        ideal_spe_params_flatten = torch.cat(
1✔
412
            [torch.tile(ideal_spe_params[:,i], (n_samples_per_dataset[i],1)).transpose(0,1) for i in range (n_realizations)], # (n_realizations,) of (n_spe_params, [n_samples depends on dataset],)
413
            axis = 1
414
        ) # (n_spe_params, n_all_samples)
415

416
        ideal_class_params_flatten = torch.tile(ideal_class_params, (n_all_samples,1)).transpose(0,1) # (n_class_params, n_all_samples)
1✔
417

418
        def trial_func (X, params, class_params):
×
419
            y = params[0]*torch.exp(-params[1]*X[0])*torch.cos(class_params[0]*X[0]+params[2]) + class_params[1]*X[1]
1✔
420
            return y
1✔
421

422
        y_ideals_flatten = trial_func (multi_X_flatten, ideal_spe_params_flatten, ideal_class_params_flatten) # (n_all_samples,)
1✔
423
        multi_y_target   = unflatten_multi_data(y_ideals_flatten)                                         # (n_realizations,) of (n_samples depends on dataset,)
×
424

425
        k0_init = [1.,1.,1.]*10 # np.full(n_realizations, 1.)
1✔
426
        # consts
427
        pi     = data_conversion (np.pi) .to(DEVICE)
×
428
        const1 = data_conversion (1.)    .to(DEVICE)
1✔
429

430
        # LIBRARY CONFIG
431
        args_make_tokens = {
1✔
432
                        # operations
433
                        "op_names"             : "all",
434
                        "use_protected_ops"    : True,
435
                        # input variables
436
                        "input_var_ids"        : {"t" : 0         , "l" : 1          },
437
                        "input_var_units"      : {"t" : [0, 1, 0] , "l" : [1, 0, 0]  },
438
                        "input_var_complexity" : {"t" : 0.        , "l" : 1.         },
439
                        # constants
440
                        "constants"            : {"pi" : pi        , "const1" : const1    },
441
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] },
442
                        "constants_complexity" : {"pi" : 1.        , "const1" : 1.        },
443
                        # free constants
444
                        "class_free_constants"            : {"c0"              , "c1"               },
445
                        "class_free_constants_init_val"   : {"c0" : 1.         , "c1"  : 1.         },
446
                        "class_free_constants_units"      : {"c0" : [0, -1, 0] , "c1"  : [0, -1, 0] },
447
                        "class_free_constants_complexity" : {"c0" : 1.         , "c1"  : 1.         },
448
                        # free constants
449
                        "spe_free_constants"            : {"k0"              , "k1"               , "k2"               },
450
                        "spe_free_constants_init_val"   : {"k0" : k0_init    , "k1"  : 1.         , "k2"  : 1.         },
451
                        "spe_free_constants_units"      : {"k0" : [1, -1, 0] , "k1"  : [0, -1, 0] , "k2"  : [0, 0, 0]  },
452
                        "spe_free_constants_complexity" : {"k0" : 1.         , "k1"  : 1.         , "k2"  : 1.         },
453
                           }
454

455
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
456
                                "superparent_units" : [1, -1, 0],
457
                                "superparent_name"  : "v",
458
                                }
459

460
        # --- PRIORS ---
461
        priors_config  = [ ("UniformArityPrior", None),
1✔
462
                           ("HardLengthPrior", {"min_length": 1,
463
                                                "max_length": 20, }),
464
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
465

466
        # --- FREE CONST OPTI ---
467
        free_const_opti_args = {
1✔
468
            'loss'   : "MSE",
469
            'method' : 'LBFGS',
470
            'method_args': {
471
                        'n_steps' : 50,
472
                        'tol'     : 1e-6,
473
                        'lbfgs_func_args' : {
474
                            'max_iter'       : 4,
475
                            'line_search_fn' : "strong_wolfe",
476
                                             },
477
                            },
478
        }
479

480

481
        # --- BATCH ---
482
        batch_size    = 100
1✔
483
        max_time_step = 30
1✔
484

485
        my_batch = batch.Batch(library_args     = library_args,
1✔
486
                               priors_config    = priors_config,
487
                               batch_size       = batch_size,
488
                               max_time_step    = max_time_step,
489
                               rewards_computer = reward.make_RewardsComputer (reward_function     = reward.SquashedNRMSE,
490
                                                                               zero_out_unphysical = True,
491
                                                                               ),
492
                               free_const_opti_args = free_const_opti_args,
493
                               multi_X         = multi_X,
494
                               multi_y         = multi_y_target,
495
                               multi_y_weights = multi_y_weights,
496
                               )
497

498
        target_prog_str = ["add", "mul", "mul", "k0", "exp", "mul", "neg", "k1", "t", "cos", "add", "mul", "c0", "t",
1✔
499
                           "k2", "mul", "c1", "l", ]
500
        target_prog_idx = [my_batch.library.lib_name_to_idx[name] for name in target_prog_str]
×
501
        target_prog_idx += [0]*(max_time_step-len(target_prog_idx)) # Padding with zeros to max_time_step
×
502
        target_prog_idx = np.array(target_prog_idx)
1✔
503

504
        # --- DUMMY EPOCH ---
505
        t0 = time.perf_counter()
1✔
506
        for step in range(max_time_step):
1✔
507
            # Embedding output
508
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
1✔
509
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
×
510
            # Dummy model output
511
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
1✔
512
            # Cheating by setting the target program in the first batch element of probs
513
            probs[0]                        = 0.  # Zeroing out all probs
1✔
514
            probs[0, target_prog_idx[step]] = 1.  # Setting the target program to 1
1✔
515
            # Actions
516
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
1✔
517
            actions      = actions.cpu().numpy()
1✔
518
            my_batch.programs.append(actions)
×
519
        # Embedding output
520
        lengths = my_batch.programs.n_lengths
1✔
521
        R       = my_batch.get_rewards()
1✔
522
        # Computing model loss using (probs,actions, R, lengths)
523
        # ...
524
        t1 = time.perf_counter()
1✔
525
        eps = 1e-3
×
526
        n_solutions = (np.abs(1-R) < eps).sum()
1✔
527
        print("Dummy epoch time (mdho2d scenario) = %f ms (found %i/%i candidates with R = 1 +/- %f)"%((t1-t0)*1e3, n_solutions, batch_size, eps))
×
528
        return None
×
529

530
    def test_dummy_epoch_free_consts_and_duplicate_elimination(self):
1✔
531

532
        # ------- TEST CASE -------
533
        DEVICE = 'cpu'
×
534
        if torch.cuda.is_available():
1✔
535
            DEVICE = 'cuda'
1✔
536

537
        # --- DATA ---
538
        N = int(1e3)
1✔
539
        x_array = np.linspace(0.04, 4, N)
1✔
540
        x = data_conversion (x_array).to(DEVICE)
1✔
541
        X = torch.stack((x,), axis=0)
1✔
542
        pi = data_conversion (np.pi).to(DEVICE)
1✔
543
        const1 = data_conversion (1.).to(DEVICE)
×
544
        T = 1.028
×
545
        v0 = 0.995
×
546
        y_target = data_conversion(x_array/T + v0).to(DEVICE)
1✔
547

548

549
        # --- LIBRARY CONFIG ---
550
        args_make_tokens = {
1✔
551
                        # operations
552
                        "op_names"             : ["add", "div"],
553
                        "use_protected_ops"    : True,
554
                        # input variables
555
                        "input_var_ids"        : {"x" : 0         },
556
                        "input_var_units"      : {"x" : [1, 0, 0] },
557
                        "input_var_complexity" : {"x" : 0.        },
558
                        # constants
559
                        "constants"            : {"pi" : pi        , "const1" : const1    },
560
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] },
561
                        "constants_complexity" : {"pi" : 0.        , "const1" : 1.        },
562
                        # free constants
563
                        "free_constants"            : {"T"              , "v0"              ,},
564
                        "free_constants_init_val"   : {"T" : 1.         , "v0" : 1.         ,},
565
                        "free_constants_units"      : {"T" : [0, 1, 0] , "v0" : [1, -1, 0] ,},
566
                        "free_constants_complexity" : {"T" : 0.         , "v0" : 0.         ,},
567
                            }
568
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
569
                        "superparent_units" : [1, -1, 0],
570
                        "superparent_name"  : "v",
571
                        }
572

573
        # --- PRIORS ---
574
        priors_config  = [ ("UniformArityPrior", None),
1✔
575
                           ("HardLengthPrior", {"min_length": 1,
576
                                               "max_length": 5, }),
577
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
578

579
        # --- FREE CONST OPTI ---
580
        free_const_opti_args = {
1✔
581
            'loss'   : "MSE",
582
            'method' : 'LBFGS',
583
            'method_args': {
584
                        'n_steps' : 30,
585
                        'tol'     : 1e-6,
586
                        'lbfgs_func_args' : {
587
                            'max_iter'       : 4,
588
                            'line_search_fn' : "strong_wolfe",
589
                                             },
590
                            },
591
        }
592

593
        # --- BATCH ---
594
        batch_size    = 1000
1✔
595
        max_time_step = 10
×
596

597
        multi_X = [X,]
1✔
598
        multi_y = [y_target,]
1✔
599

600
        my_batch = batch.Batch(library_args     = library_args,
1✔
601
                               priors_config    = priors_config,
602
                               batch_size       = batch_size,
603
                               max_time_step    = max_time_step,
604
                               rewards_computer = reward.make_RewardsComputer (reward_function     = reward.SquashedNRMSE,
605
                                                                               zero_out_unphysical = True,
606
                                                                               zero_out_duplicates = True,),
607
                               free_const_opti_args = free_const_opti_args,
608
                               multi_X = multi_X,
609
                               multi_y = multi_y,
610
                               )
611

612
        # --- DUMMY EPOCH ---
613
        t0 = time.perf_counter()
1✔
614
        for step in range(max_time_step):
×
615
            # Embedding output
616
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
×
617
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
1✔
618
            # Dummy model output
619
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
×
620
            # Actions
621
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
1✔
622
            actions      = actions.cpu().numpy()
×
623
            my_batch.programs.append(actions)
×
624
        # Embedding output
625
        lengths = my_batch.programs.n_lengths
1✔
626
        R       = my_batch.get_rewards()
1✔
627
        # Computing model loss using (probs,actions, R, lengths)
628
        # ...
629
        t1 = time.perf_counter()
1✔
630
        eps = 1e-5
×
631
        n_solutions = (np.abs(1-R) < eps).sum()
1✔
632
        n_kept = (R>0).sum()
×
633
        print("Dummy epoch time (w free const and duplicate elimination) = %f ms (found %i/%i candidates with R > 0 "
1✔
634
              "and %i/%i with R = 1 +/- %f)"%((t1-t0)*1e3, n_kept, batch_size, n_solutions, batch_size, eps))
635

636
    def test_dummy_epoch_free_consts_and_duplicate_elimination_and_lowest_complexity(self):
×
637

638
        # ------- TEST CASE -------
639
        DEVICE = 'cpu'
1✔
640
        if torch.cuda.is_available():
1✔
641
            DEVICE = 'cuda'
1✔
642

643
        # --- DATA ---
644
        N = int(1e3)
1✔
645
        x_array = np.linspace(0.04, 4, N)
1✔
646
        x = data_conversion (x_array).to(DEVICE)
1✔
647
        X = torch.stack((x,), axis=0)
1✔
648
        pi = data_conversion (np.pi).to(DEVICE)
×
649
        const1 = data_conversion (1.).to(DEVICE)
×
650
        T = 1.028
×
651
        v0 = 0.995
1✔
652
        y_target = data_conversion(x_array/T + v0).to(DEVICE)
×
653

654

655
        # --- LIBRARY CONFIG ---
656
        args_make_tokens = {
1✔
657
                        # operations
658
                        "op_names"             : ["add", "div"],
659
                        "use_protected_ops"    : True,
660
                        # input variables
661
                        "input_var_ids"        : {"x" : 0         },
662
                        "input_var_units"      : {"x" : [1, 0, 0] },
663
                        "input_var_complexity" : {"x" : 0.        },
664
                        # constants
665
                        "constants"            : {"pi" : pi        , "const1" : const1    },
666
                        "constants_units"      : {"pi" : [0, 0, 0] , "const1" : [0, 0, 0] },
667
                        "constants_complexity" : {"pi" : 0.        , "const1" : 1.        },
668
                        # free constants
669
                        "free_constants"            : {"T"              , "v0"              ,},
670
                        "free_constants_init_val"   : {"T" : 1.         , "v0" : 1.         ,},
671
                        "free_constants_units"      : {"T" : [0, 1, 0] , "v0" : [1, -1, 0] ,},
672
                        "free_constants_complexity" : {"T" : 0.         , "v0" : 0.         ,},
673
                            }
674
        library_args = {"args_make_tokens"  : args_make_tokens,
1✔
675
                        "superparent_units" : [1, -1, 0],
676
                        "superparent_name"  : "v",
677
                        }
678

679
        # --- PRIORS ---
680
        priors_config  = [ ("UniformArityPrior", None),
1✔
681
                           ("HardLengthPrior", {"min_length": 1,
682
                                               "max_length": 5, }),
683
                           ("PhysicalUnitsPrior", {"prob_eps": np.finfo(np.float32).eps})]
684

685
        # --- FREE CONST OPTI ---
686
        free_const_opti_args = {
1✔
687
            'loss'   : "MSE",
688
            'method' : 'LBFGS',
689
            'method_args': {
690
                        'n_steps' : 30,
691
                        'tol'     : 1e-6,
692
                        'lbfgs_func_args' : {
693
                            'max_iter'       : 4,
694
                            'line_search_fn' : "strong_wolfe",
695
                                             },
696
                            },
697
        }
698

699
        # --- BATCH ---
700
        batch_size    = 1000
×
701
        max_time_step = 10
1✔
702

703
        multi_X = [X,]
1✔
704
        multi_y = [y_target,]
1✔
705

706
        my_batch = batch.Batch(library_args     = library_args,
1✔
707
                               priors_config    = priors_config,
708
                               batch_size       = batch_size,
709
                               max_time_step    = max_time_step,
710
                               rewards_computer = reward.make_RewardsComputer (reward_function     = reward.SquashedNRMSE,
711
                                                                               zero_out_unphysical = True,
712
                                                                               zero_out_duplicates = True,
713
                                                                               keep_lowest_complexity_duplicate = True),
714
                               free_const_opti_args = free_const_opti_args,
715
                               multi_X = multi_X,
716
                               multi_y = multi_y,
717
                               )
718

719
        # --- DUMMY EPOCH ---
720
        t0 = time.perf_counter()
×
721
        for step in range(max_time_step):
1✔
722
            # Embedding output
723
            prior        = torch.tensor(my_batch.prior().astype(np.float32),   requires_grad=False)                          # (batch_size, n_choices)
1✔
724
            observations = torch.tensor(my_batch.get_obs().astype(np.float32), requires_grad=False)                          # (batch_size, 3*n_choices+1)
1✔
725
            # Dummy model output
726
            probs        = torch.tensor(np.random.rand(my_batch.batch_size, my_batch.library.n_choices).astype(np.float32))  # (batch_size, n_choices,)
1✔
727
            # Actions
728
            actions      = torch.multinomial(probs * prior, num_samples=1)[:, 0]
×
729
            actions      = actions.cpu().numpy()
×
730
            my_batch.programs.append(actions)
1✔
731
        # Embedding output
732
        lengths = my_batch.programs.n_lengths
1✔
733
        R       = my_batch.get_rewards()
1✔
734
        # Computing model loss using (probs,actions, R, lengths)
735
        # ...
736
        t1 = time.perf_counter()
1✔
737
        eps = 1e-5
×
738
        n_solutions = (np.abs(1-R) < eps).sum()
1✔
739
        n_kept = (R>0).sum()
×
740
        print("Dummy epoch time (w free const and duplicate elimination, keeping lowest complexity) = %f ms (found "
×
741
              "%i/%i candidates with R > 0 and %i/%i with R = 1 +/- %f)"%(
742
                (t1-t0)*1e3, n_kept, batch_size, n_solutions, batch_size, eps))
743

744
if __name__ == '__main__':
×
745
    unittest.main(verbosity=2)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc