Skip to content

quast_decisiontree.algorithms.classical.brute_force

quast_decisiontree.algorithms.classical.brute_force

Brute-force fallback classical optimizer. A wrapper around scipy.optimize.brute.

BruteForce

Bases: ClassicalAlgorithm

Exhaustive binary optimizer for small QUBO matrices.

Source code in src/quast_decisiontree/algorithms/classical/brute_force.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
class BruteForce(ClassicalAlgorithm):
    """Exhaustive binary optimizer for small QUBO matrices."""

    @classmethod
    def check_input(cls, opt_problem: Any) -> bool:
        """Check whether ``opt_problem`` is a valid QUBO input.

        Args:
            opt_problem: The problem description to check.

        Returns:
            True if ``opt_problem`` is a valid QUBO matrix, False otherwise.
        """
        return is_qubo_matrix(opt_problem)

    def execute(self, opt_problem: Any, classical_args: Any = None) -> tuple[list[int], float]:  # pylint: disable=unused-argument
        """Return a brute-force binary solution vector and its objective value.

        Args:
            opt_problem: A QUBO matrix whose bilinear form is minimized.
            classical_args: Present for signature compatibility; unused.

        Returns:
            A tuple ``(solution_vector, objective_value)``.

        Raises:
            TypeError: If ``opt_problem`` is not a valid QUBO matrix.
        """
        if not self.check_input(opt_problem):
            raise TypeError(
                "Invalid input for solver. Either not array-like or not quadratic and 2D"
            )

        def objective(vector):
            return np.linalg.multi_dot([vector, opt_problem, vector])

        ranges = [(0, 1)] * np.shape(opt_problem)[0]
        solution_vector = brute(objective, ranges, Ns=2, finish=None)
        solution_value = objective(solution_vector)

        return [int(elem) for elem in solution_vector], solution_value

check_input classmethod

check_input(opt_problem)

Check whether opt_problem is a valid QUBO input.

Parameters:

Name Type Description Default
opt_problem Any

The problem description to check.

required

Returns:

Type Description
bool

True if opt_problem is a valid QUBO matrix, False otherwise.

Source code in src/quast_decisiontree/algorithms/classical/brute_force.py
24
25
26
27
28
29
30
31
32
33
34
@classmethod
def check_input(cls, opt_problem: Any) -> bool:
    """Check whether ``opt_problem`` is a valid QUBO input.

    Args:
        opt_problem: The problem description to check.

    Returns:
        True if ``opt_problem`` is a valid QUBO matrix, False otherwise.
    """
    return is_qubo_matrix(opt_problem)

execute

execute(opt_problem, classical_args=None)

Return a brute-force binary solution vector and its objective value.

Parameters:

Name Type Description Default
opt_problem Any

A QUBO matrix whose bilinear form is minimized.

required
classical_args Any

Present for signature compatibility; unused.

None

Returns:

Type Description
tuple[list[int], float]

A tuple (solution_vector, objective_value).

Raises:

Type Description
TypeError

If opt_problem is not a valid QUBO matrix.

Source code in src/quast_decisiontree/algorithms/classical/brute_force.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def execute(self, opt_problem: Any, classical_args: Any = None) -> tuple[list[int], float]:  # pylint: disable=unused-argument
    """Return a brute-force binary solution vector and its objective value.

    Args:
        opt_problem: A QUBO matrix whose bilinear form is minimized.
        classical_args: Present for signature compatibility; unused.

    Returns:
        A tuple ``(solution_vector, objective_value)``.

    Raises:
        TypeError: If ``opt_problem`` is not a valid QUBO matrix.
    """
    if not self.check_input(opt_problem):
        raise TypeError(
            "Invalid input for solver. Either not array-like or not quadratic and 2D"
        )

    def objective(vector):
        return np.linalg.multi_dot([vector, opt_problem, vector])

    ranges = [(0, 1)] * np.shape(opt_problem)[0]
    solution_vector = brute(objective, ranges, Ns=2, finish=None)
    solution_value = objective(solution_vector)

    return [int(elem) for elem in solution_vector], solution_value