Variable Conversion

In general, the Ising machines used in QA-BBO can directly handle only binary decision variables. However, practical black-box optimization problems often involve not only binary variables but also integer, real, or mixed-type decision variables. To support such non-binary variables, Amplify-BBOpt internally performs variable conversion when necessary.

Timing of variable conversion

When variable conversion is required (i.e., when the decision variables include integer or real variables), variables are converted at one of two stages: pre-encoding or post-encoding. You can specify when the conversion should take place by setting the pre_encoding argument when instantiating Optimizer. The default setting is pre_encoding = True.

from amplify_bbopt import Optimizer

# Instantiate the optimizer class (using pre-encoding; default setting)
optimizer = Optimizer(
    blackbox_func,
    trainer,
    client,
    pre_encoding=True,
)

# Instantiate the optimizer class (using post-encoding)
optimizer = Optimizer(
    blackbox_func,
    trainer,
    client,
    pre_encoding=False,
)

Note

In the above code, blackbox_func, trainer, and client refer to the previously defined black-box function, surrogate model function, and the Amplify SDK solver client, respectively. For details on their setup, see “Running the Optimization”.

Pre-encoding (Default)

Pre-encoding is a variable conversion method in which encoding is performed before constructing the surrogate model function. Since the surrogate model is trained using the encoded training data, its inputs consist only of binary values. An additional advantage of pre-encoding is that it allows the surrogate model to represent relationships of a degree higher than that of the model’s inherent polynomial order as a result of the encoding process.

Pre-encoding is automatically performed within Amplify-BBOpt. The following diagram illustrates the processing flow for pre-encoding.

_images/pre_encoding.drawio.svg

Post-encoding

Post-encoding is a variable conversion method in which encoding is performed after constructing the surrogate model function. In this approach, the surrogate model is built directly using the original training data provided by the user. Therefore, the type of the inputs to the surrogate model depend on the original data values, not on encoded representations. The function form that the surrogate model can express is limited by the polynomial order considered in the surrogate model (typically second order).

Post-encoding is carried out either within Amplify-BBOpt or as part of the internal process of the Amplify SDK. The following diagram illustrates the processing flow for post-encoding. EncodingMethod is the class related to encoding, which is explained in the next section.

_images/post_encoding.drawio.svg

Encoding types and settings

Encoding method available for pre-encoding

When using pre-encoding, you can choose between two encoding methods: domain-wall (default) and one-hot encoding. These methods can be specified using the EncodingMethod class.

  • EncodingMethod class

    This class defines the encoding method and provides two selectable attributes: DomainWall (domain-wall) and OneHot (one-hot). The default is domain-wall. The encoding method can be specified when defining decision variables as follows:

    Example: Specifying encoding method for the integer and real varaibles.

    >>> from amplify_bbopt import EncodingMethod, IntegerVariable, RealVariable
    
    >>> z_0 = IntegerVariable(bounds=(0, 5), encoding=EncodingMethod.OneHot)
    >>> x_0 = RealVariable(bounds=(0, 1.5), encoding=EncodingMethod.OneHot)
    >>> print(z_0.encoding.method)
    EncodingMethod.OneHot
    >>> print(x_0.encoding.method)
    EncodingMethod.OneHot
    

    Example: Specifying encoding method for the integer and real varaibles.

    >>> from amplify_bbopt import EncodingMethod, IntegerVariable, RealVariable
    
    >>> z_1 = IntegerVariable(bounds=(0, 5))
    >>> x_1 = RealVariable(bounds=(0, 1.5))
    >>> print(z_1.encoding.method)
    EncodingMethod.DomainWall
    >>> print(x_1.encoding.method)
    EncodingMethod.DomainWall
    

In the case of real decision variables, the range specified by bounds must be discretized into discrete points. This discretization behavior can be controlled using the classes DiscretizationSpec and DiscretizationMethod, as summarized below.

  • DiscretizationSpec class

    This class defines how discretization is performed, with the following key attributes: method (discretization method) and num_bins (number of discrete points). By default, method=DiscretizationMethod.Uniform and num_bins=11 are used, meaning that the real variable range is divided into 11 equally spaced discrete points.

    The DiscretizationMethod class defines available discretization schemes: Uniform (uniform discretization) and LogUniform (log-uniform discretization).

    Example: Specifying the number of discretization points for a real variable.

    >>> from amplify_bbopt import DiscretizationSpec, RealVariable
    
    >>> x_2 = RealVariable(
    ...     bounds=(1.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(num_bins=7),
    ... )
    >>> print(x_2.possible_values)
    [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]
    

    Example: Specifying the discretization method and the number of points for a real variable.

    >>> from amplify_bbopt import RealVariable, DiscretizationSpec, DiscretizationMethod
    
    >>> x_3 = RealVariable(
    ...     bounds=(1.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(
    ...         method=DiscretizationMethod.LogUniform,
    ...         num_bins=7,
    ...     ),
    ... )
    >>> print(x_3.possible_values)
    [1.0, 1.2599210498948732, 1.5874010519681994, 2.0, 2.5198420997897464, 3.174802103936399, 4.0]
    

    Caution

    When using log-uniform discretization (DiscretizationMethod.LogUniform), the range (bounds) of the real variable must be positive.

    >>> from amplify_bbopt import RealVariable, DiscretizationSpec, DiscretizationMethod
    
    >>> x_3 = RealVariable(
    ...     bounds=(0.0, 4.0),
    ...     discretization_spec=DiscretizationSpec(
    ...         method=DiscretizationMethod.LogUniform
    ...     ),
    ... )
    Traceback (most recent call last):
        ...
    ValueError: Lower bound must be greater than 0 for `LogUniform` discretization.
    

Encoding methods available for post-encoding

When using post-encoding, the available encoding methods are: EncodingMethod.DomainWall, EncodingMethod.OneHot, and EncodingMethod.Amplify.

If EncodingMethod.Amplify is selected, the variable conversion is performed internally within the Amplify SDK according to its default encoding method.

For details on variable conversion handled by the Amplify SDK, see the official documentation pages: Encoding integer variables into binary variables and Encoding real variables into binary variables.