moptipy.operators package¶
In this package, we provide implementations for basic search operators.
In
bitstrings
, you can find operators for elements from thebitstrings
space.In
ordered_choices
, you can find operators for elements from theordered_choices
space.In
permutations
, you can find operators for elements from thepermutations
space.In
vectors
, you can find operators for elements from thevectorspace
.
Subpackages¶
- moptipy.operators.bitstrings package
- moptipy.operators.ordered_choices package
- moptipy.operators.permutations package
- Submodules
- moptipy.operators.permutations.op0_shuffle module
- moptipy.operators.permutations.op1_insert1 module
- moptipy.operators.permutations.op1_swap2 module
- moptipy.operators.permutations.op1_swap_exactly_n module
- moptipy.operators.permutations.op1_swap_try_n module
- moptipy.operators.permutations.op1_swapn module
- moptipy.operators.permutations.op2_gap module
- moptipy.operators.permutations.op2_ox2 module
- moptipy.operators.signed_permutations package
- moptipy.operators.vectors package
Submodules¶
moptipy.operators.op0_forward module¶
A nullary operator forwarding to another function.
This is a nullary operator (an instance of Op0
) whose method op0()
forwards to another Callable. This other Callable can then return a solution that is created in some special way, or maybe even the current best solution of a search process.
This operator has been designed to be used in conjunction with from_starting_point()
, which is an optimization Process
where a starting point has been defined, i.e., where the methods get_copy_of_best_x()
and get_best_f()
return pre-defined values. By setting forward_to()
to get_copy_of_best_x()
, this nullary operator will return the current-best solution of the optimization process, which, in this case, will be the pre-defined starting point. Any optimization algorithm (e.g., an instance of Algorithm0
) using this nullary operator to get its initial solution will then begin the search at this pre-defined starting point. This allows using one algorithm as a sub-algorithm of another one. Wrapping from_starting_point()
around the result of a call to for_fes()
would allow to limit the number of objective function evaluations consumed by the sub-algorithm.
- class moptipy.operators.op0_forward.Op0Forward[source]¶
Bases:
Op0
A nullary operator that forwards all calls to op0 to a Callable.
- op0(random, dest)[source]¶
Forward the call.
- Parameters:
random (
Generator
) – ignoreddest (
ndarray
) – the destination data structure to be filled with the data of the point in the search space by the internal Callable set byforward_to()
.
- Return type:
moptipy.operators.tools module¶
Some tools for optimization.
- moptipy.operators.tools.exponential_step_size(step_size, min_steps, max_steps)[source]¶
Translate a step size in [0,1] to an integer in min_steps..max_steps.
The idea is that we would like to have step-size dependent operators of type
Op1WithStepSize
. These operators allow algorithms to tune the amount of change to be applied to a solution between 0 and 1 (inclusively). As described in the documentation ofop1()
, 0 means that the smallest possible change should be applied and 1 means that the largest possible change should be applied.Now for many search spaces, we need to translate this step size from [0,1] to an integer. For instance, if we have n-dimensional
bitstrings
as search space, then we can flip anything between 1 and n bits. Straightforwardly, one would linearly scale the step size from [0,1] to 1..n. Unfortunately, if we do that, then different values of step_size will have very different meaning depending on n. For example, step_size=0.05 would translate to round(1 + step_size * (n-1)) = 1 bits to be flipped if n=10, to 6 bit flips for n=100, and to 501 bit flips for n=10_000. While flipping one bit is a very small move and flipping six bits may be a medium-size move in discrete optimization, flipping over 500 bits is actually always quite a lot.What we would like is to have scale-independent small moves but still be able to make large moves. We can get this by exponentially transforming the step_width. Most step_size values will result in small integer steps and only step_size values close to 1 will yield really big results.
And for a step_size=0.05, we get for different n:
>>> exponential_step_size(0.05, 1, 10) 1 >>> exponential_step_size(0.05, 1, 100) 1 >>> exponential_step_size(0.05, 1, 10_000) 2 >>> exponential_step_size(0.05, 1, 1_000_000) 2 >>> exponential_step_size(0.05, 1, 1_000_000_000) 3 >>> exponential_step_size(0.05, 1, 1_000_000_000_000) 4
For different values of step_size and a fixed n, we can still obtain the whole spectrum of possible changes. For n=10, for example, we get:
>>> exponential_step_size(0.0, 1, 10) 1 >>> exponential_step_size(0.1, 1, 10) 1 >>> exponential_step_size(0.2, 1, 10) 2 >>> exponential_step_size(0.3, 1, 10) 2 >>> exponential_step_size(0.4, 1, 10) 3 >>> exponential_step_size(0.5, 1, 10) 3 >>> exponential_step_size(0.6, 1, 10) 4 >>> exponential_step_size(0.7, 1, 10) 5 >>> exponential_step_size(0.8, 1, 10) 6 >>> exponential_step_size(0.85, 1, 10) 7 >>> exponential_step_size(0.9, 1, 10) 8 >>> exponential_step_size(0.95, 1, 10) 9 >>> exponential_step_size(1.0, 1, 10) 10
So we can still reach the whole range of possible steps from 1 to n.
>>> isinstance(exponential_step_size(0.5, 1, 9), int) True >>> exponential_step_size(0.0, 1, 100) 1 >>> exponential_step_size(1.0, 1, 100) 100 >>> exponential_step_size(1.0 / 3.0, 1, 10) 2 >>> exponential_step_size(1.0 / 3.0, 1, 100) 5 >>> exponential_step_size(1.0 / 3.0, 1, 10_000) 22 >>> exponential_step_size(0.0, 2, 10) 2 >>> exponential_step_size(0.0, 9, 10) 9 >>> exponential_step_size(0.0, 10, 10) 10 >>> exponential_step_size(1.0, 10, 10) 10
- moptipy.operators.tools.inv_exponential_step_size(int_val, min_steps, max_steps)[source]¶
Compute the inverse of
exponential_step_size()
.This routine exists mainly to make testing easier.
- Parameters:
int_val (
int
) – the return value ofexponential_step_size()
.min_steps (
int
) – the minimum (inclusive) value any int_valmax_steps (
int
) – the maximum (inclusive) value any int_val
- Return type:
>>> exponential_step_size(0.47712125471966244, 1, 10) 3 >>> inv_exponential_step_size(3, 1, 10) 0.47712125471966244 >>> inv_exponential_step_size(1, 1, 10) 0.0 >>> inv_exponential_step_size(10, 1, 10) 1.0 >>> inv_exponential_step_size(33, 6, 673) 0.5123088678224029 >>> exponential_step_size(0.5123088678224029, 6, 673) 33 >>> inv_exponential_step_size(3, 3, 3) 1.0 >>> inv_exponential_step_size(3, 3, 10) 0.0 >>> inv_exponential_step_size(10, 3, 10) 1.0