Example #1
0
def test_qubo_checkkey():

    with assert_raises(KeyError):
        QUBOMatrix({('a', ): -1})

    with assert_raises(KeyError):
        QUBOMatrix({0: -1})

    with assert_raises(KeyError):
        QUBOMatrix({(0, 1, 2): -1})
Example #2
0
def test_create_var():

    d = QUBOMatrix.create_var(0)
    assert d == {(0, ): 1}
    assert d.name == 0
    assert type(d) == QUBOMatrix

    d = QUBOMatrix.create_var(1)
    assert d == {(1, ): 1}
    assert d.name == 1
    assert type(d) == QUBOMatrix
Example #3
0
def test_symbols():

    a, b = Symbol('a'), Symbol('b')
    d = QUBOMatrix()
    d[(0, )] -= a
    d[(0, 1)] += 2
    d[(1, )] += b
    assert d == {(0, ): -a, (0, 1): 2, (1, ): b}
    assert d.subs(a, 2) == {(0, ): -2, (0, 1): 2, (1, ): b}
    assert d.subs(b, 1) == {(0, ): -a, (0, 1): 2, (1, ): 1}
    assert d.subs({a: -3, b: 4}) == {(0, ): 3, (0, 1): 2, (1, ): 4}
Example #4
0
def test_qubo_remove_value_when_zero():

    d = QUBOMatrix()
    d[(0, 0)] += 1
    d[(0, 0)] -= 1
    assert d == {}

    d.refresh()
    assert d.degree == 0
    assert d.num_binary_variables == 0
    assert d.variables == set()
Example #5
0
def test_qubo_to_quso_to_qubo():

    qubo = {(0, ): 1, (0, 1): 1, (1, ): -1, (1, 2): .2, (): -2, (2, ): 1}
    assert qubo == quso_to_qubo(qubo_to_quso(qubo))

    # type asserting
    assert type(qubo_to_quso(qubo)) == QUSO
    assert type(qubo_to_quso(QUBOMatrix(qubo))) == QUSOMatrix
    assert type(qubo_to_quso(QUBO(qubo))) == QUSO

    qubo = {
        ('0', ): 1,
        ('0', 1): 1,
        (1, ): -1,
        (1, '2'): .2,
        (): -2,
        ('2', ): 1,
        (0, 0): 1
    }
    # need to reformat qubo so it is sorted with the same hash
    assert QUBO(qubo) == quso_to_qubo(qubo_to_quso(qubo))

    # type asserting
    assert type(qubo_to_quso(qubo)) == QUSO
    assert type(qubo_to_quso(QUBO(qubo))) == QUSO
Example #6
0
    def to_qubo(self, A=None, B=1):
        r"""to_qubo.

        Create and return the BILP problem in QUBO form following
        section 3 of [Lucas]. The Q matrix for the QUBO
        will be returned as an uppertriangular dictionary. Thus, the problem
        becomes minimizing :math:`\sum_{i \leq j} x_i x_j Q_{ij}`. ``A`` and
        ``B`` are parameters to enforce constraints.

        Parameters
        ----------
        A: positive float (optional, defaults to None).
            A enforces the constraints. If ``A`` is
            None, then a default value will be chosen as given in section 3 of
            [Lucas].
        B: positive float that is less than A (optional, defaults to 1).
            See section 3 of [Lucas].

        Return
        ------
        Q : qubovert.utils.QUBOMatrix object.
            The upper triangular QUBO matrix, a QUBOMatrix object.
            For most practical purposes, you can use QUBOMatrix in the
            same way as an ordinary dictionary. For more information,
            see help(qubovert.utils.QUBOMatrix).

        """
        # all naming conventions follow the paper listed in the docstring
        if A is None:
            A = B * self._N

        Q = QUBOMatrix()

        # equation 23
        for i in range(self._N):
            Q[(i, )] += B * self._c[i]

        # equation 22
        for j in range(self._m):
            Qtemp = QUBOMatrix()
            Qtemp += self._b[j]
            for i in range(self._N):
                Qtemp[(i, )] -= self._S[j][i]
            Qtemp *= A * Qtemp
            Q += Qtemp

        return Q
Example #7
0
def test_round():

    d = QUBOMatrix({(0, ): 3.456, (1, ): -1.53456})

    assert round(d) == {(0, ): 3, (1, ): -2}
    assert round(d, 1) == {(0, ): 3.5, (1, ): -1.5}
    assert round(d, 2) == {(0, ): 3.46, (1, ): -1.53}
    assert round(d, 3) == {(0, ): 3.456, (1, ): -1.535}
Example #8
0
def test_properties():

    Q = QUBOMatrix()
    Q[(0, )] -= 1
    Q[(0, 1)] += 1
    Q += 2
    assert Q.offset == 2
    assert Q.Q == {(0, 0): -1, (0, 1): 1}
def test_qubosimulation_bigrun():

    # test that it runs on a big problem
    model = QUBOMatrix({(i, j): 1
                        for i in range(2, 200, 3) for j in range(2, 200, 2)})
    sim = QUBOSimulation(model)
    sim.update(3, 1000)
    sim.update(3, 1000, in_order=True)
Example #10
0
def test_qubomatrix_solve_bruteforce():

    Q = QUBOMatrix({(0, 1): 1, (1, 2): 1, (1, 1): -1, (2, ): -2})
    sol = Q.solve_bruteforce()
    assert sol == {0: 0, 1: 0, 2: 1}
    assert allclose(Q.value(sol), -2)

    Q = QUBOMatrix({(0, 0): 1, (0, 1): -1, (): 1})
    sols = Q.solve_bruteforce(True)
    assert sols == [{0: 0, 1: 0}, {0: 0, 1: 1}, {0: 1, 1: 1}]
    assert all(allclose(Q.value(s), 1) for s in sols)
Example #11
0
def test_normalize():

    temp = {(0, ): 4, (1, ): -2}
    d = QUBOMatrix(temp)
    d.normalize()
    assert d == {k: v / 4 for k, v in temp.items()}

    temp = {(0, ): -4, (1, ): 2}
    d = QUBOMatrix(temp)
    d.normalize()
    assert d == {k: v / 4 for k, v in temp.items()}
Example #12
0
def test_qubo_degree():

    d = QUBOMatrix()
    assert d.degree == 0
    d[(0, )] += 2
    assert d.degree == 1
    d[(1, )] -= 3
    assert d.degree == 1
    d[(1, 2)] -= 2
    assert d.degree == 2
Example #13
0
def test_qubo_addition():

    temp = QUBOMatrix({(0, 0): 1, (0, 1): 2})
    temp1 = {(0, ): -1, (1, 0): 3}
    temp2 = {(0, 1): 5}
    temp3 = {(0, ): 2, (0, 1): -1}

    # add constant
    d = temp.copy()
    d += 5
    d[()] -= 2
    d == {(0, ): 1, (0, 1): 2, (): 3}

    # __add__
    d = temp.copy()
    g = d + temp1
    assert g == temp2

    # __iadd__
    d = temp.copy()
    d += temp1
    assert d == temp2

    # __radd__
    d = temp.copy()
    g = temp1 + d
    assert g == temp2

    # __sub__
    d = temp.copy()
    g = d - temp1
    assert g == temp3

    # __isub__
    d = temp.copy()
    d -= temp1
    assert d == temp3

    # __rsub__
    d = temp.copy()
    g = temp1 - d
    assert g == QUBOMatrix(temp3) * -1
Example #14
0
def test_matrix_to_qubo():

    matrix, qubo = [[-3, 1], [-1, 2]], {(0, ): -3, (1, ): 2}
    assert matrix_to_qubo(matrix) == qubo

    matrix, qubo = np.array([[-3, 1], [-1, 2]]), {(0, ): -3, (1, ): 2}
    assert matrix_to_qubo(matrix) == qubo

    matrix, qubo = [[-3, 1], [-1, 2]], QUBOMatrix({(0, ): -3, (1, ): 2})
    assert matrix_to_qubo(matrix) == qubo

    with assert_raises(ValueError):
        matrix_to_qubo([[1, 2, 3], [1, 0, 1]])
Example #15
0
    def to_qubo(self, A=2, B=1):
        r"""to_qubo.

        Create and return the vertex cover problem in QUBO form following
        section 4.3 of [Lucas]. The Q matrix for the QUBO
        will be returned as an uppertriangular dictionary. Thus, the problem
        becomes minimizing :math:`\sum_{i \leq j} x_i x_j Q_{ij}`. ``A`` and
        ``B`` are parameters to enforce constraints.

        It is formatted such that if all the constraints are satisfied, then
        the objective function will be equal to the total number of colored
        verticies.

        Parameters
        ----------
        A: positive float (optional, defaults to 2).
            A enforces the constraints. See section 4.3 of [Lucas].
        B: positive float that is less than A (optional, defaults to 1).
            See section 4.3 of [Lucas].

        Return
        ------
        Q : qubovert.utils.QUBOMatrix object.
            The upper triangular QUBO matrix, a QUBOMatrix object.
            For most practical purposes, you can use QUBOMatrix in the
            same way as an ordinary dictionary. For more information,
            see help(qubovert.utils.QUBOMatrix).

        Example
        -------
        >>> problem = VertexCover({(0, 1), (0, 2)})
        >>> Q = problem.to_qubo()

        """
        # all naming conventions follow the paper listed in the docstring

        Q = QUBOMatrix()

        # encode H_B (equation 34)
        for i in range(self._N):
            Q[(i, )] += B

        # encode H_A, ie each edge is adjacent to at least one colored vertex.
        for u, v in self._edges:
            iu, iv = self._vertex_to_index[u], self._vertex_to_index[v]
            Q += PCBO().add_constraint_OR(iu, iv, lam=A)

        return Q
Example #16
0
def test_pretty_str():
    def equal(expression, string):
        assert expression.pretty_str() == string

    x = [QUBOMatrix() + {(i, ): 1} for i in range(3)]
    a, b = Symbol('a'), Symbol('b')

    equal(x[0], "x(0)")
    equal(-x[0], "-x(0)")
    equal(x[0] * 0, "0")
    equal(2 * x[0] * x[1] - 3 * x[2], "2 x(0) x(1) - 3 x(2)")
    equal(0 * x[0] + 1, "1")
    equal(0 * x[0] - 1, "-1")
    equal(0 * x[0] + a, "(a)")
    equal(0 * x[0] + a * b, "(a*b)")
    equal((a + b) * (x[0] * x[1] - x[2]), "(a + b) x(0) x(1) + (-a - b) x(2)")
    equal(2 * x[0] * x[1] - x[2], "2 x(0) x(1) - x(2)")
    equal(-x[2] + x[0] * x[1], "-x(2) + x(0) x(1)")
    equal(-2 * x[2] + 2 * x[0] * x[1], "-2 x(2) + 2 x(0) x(1)")
Example #17
0
def test_qubo_to_matrix():

    matrix, qubo = [[-3, 1], [0, 2]], {(0, 0): -3, (0, 1): 1, (1, 1): 2}
    assert matrix == qubo_to_matrix(qubo, array=False)
    assert np.all(np.array(matrix) == qubo_to_matrix(qubo))

    matrix = [[-3, .5], [.5, 2]]
    assert matrix == qubo_to_matrix(qubo, array=False, symmetric=True)
    assert np.all(np.array(matrix) == qubo_to_matrix(qubo, symmetric=True))

    matrix = [[-3, 1], [0, 2]]
    qubo = QUBOMatrix({(0, 0): -3, (0, 1): 1, (1, 1): 2})
    assert matrix == qubo_to_matrix(qubo, array=False)
    assert np.all(np.array(matrix) == qubo_to_matrix(qubo))

    matrix = [[-3, .5], [.5, 2]]
    assert matrix == qubo_to_matrix(qubo, array=False, symmetric=True)
    assert np.all(np.array(matrix) == qubo_to_matrix(qubo, symmetric=True))

    with assert_raises(ValueError):
        qubo_to_matrix({})

    with assert_raises(ValueError):
        qubo_to_matrix({(): 1, (0, ): -1})
Example #18
0
    def to_qubo(self, A=2, B=1):
        r"""to_qubo.

        Create and return the set cover problem in QUBO form following section
        5.1 of [Lucas]. The Q matrix for the QUBO
        will be returned as an uppertriangular dictionary. Thus, the problem
        becomes minimizing :math:`\sum_{i \leq j} x_i x_j Q_{ij}`. A and B are
        parameters to enforce constraints.

        If all the constraints are satisfied, then the objective function
        will be equal to the total number of sets in the cover (or for
        the weighted Set Cover problem, it will equal the total weight
        of included sets in the cover).

        Parameters
        ----------
        A: positive float (optional, defaults to 2).
            A enforces the constraints. See section 5.1 of [Lucas].
        B: positive float that is less than A (optional, defaults to 1).
            See section 5.1 of [Lucas].

        Return
        ------
        Q : qubovert.utils.QUBOMatrix object.
            The upper triangular QUBO matrix, a QUBOMatrix object.
            For most practical purposes, you can use QUBOMatrix in the
            same way as an ordinary dictionary. For more information,
            see ``help(qubovert.utils.QUBOMatrix)``.

        """
        # all naming conventions follow the paper listed in the docstring

        Q = QUBOMatrix()

        Q += self._n * A  # constant comes from the constraints

        # encode H_B (equation 46)
        for i in range(self._N):
            Q[(i, )] += self._weights[i] * B

        # encode H_A

        for alpha in self._U:

            if not self._log_trick:  # (Equation 45)

                # first constraint
                for m in range(1, self._M + 1):
                    i = self._x(alpha, m)
                    Q[(i, i)] -= A
                    for mp in range(m + 1, self._M + 1):
                        ip = self._x(alpha, mp)
                        Q[(i, ip)] += 2 * A

                # second constraint
                for m in range(1, self._M + 1):
                    i = self._x(alpha, m)
                    Q[(i, i)] += A * m * m
                    for mp in range(m + 1, self._M + 1):
                        ip = self._x(alpha, mp)
                        Q[(i, ip)] += 2 * A * m * mp

                    for j in self._filtered_range(alpha):
                        Q[(j, i)] -= 2 * A * m

            else:  # using the log_trick

                # no first constraint now, but modify the second constraint.
                for m in range(self._log_M + 1):
                    i = self._x(alpha, m)
                    Q[(i, i)] += A * (pow(2, 2 * m) + 2 * pow(2, m))
                    for mp in range(m + 1, self._log_M + 1):
                        ip = self._x(alpha, mp)
                        Q[(i, ip)] += 2 * A * pow(2, m + mp)
                    for j in self._filtered_range(alpha):
                        Q[(j, i)] -= 2 * A * pow(2, m)

            for i in self._filtered_range(alpha):
                Q[(i, )] += A if not self._log_trick else -A
                for j in self._filtered_range(alpha, i + 1):
                    Q[(i, j)] += 2 * A

        return Q
Example #19
0
def test_qubo_max_index():

    d = QUBOMatrix({(0, 0): 1, (0, 3): 2})
    assert d.max_index == 3
Example #20
0
def test_num_terms():

    d = QUBOMatrix({(0, ): 1, (0, 3): 2, (0, 2): -1})
    assert d.num_terms == len(d)
Example #21
0
def test_qubo_num_binary_variables():

    d = QUBOMatrix({(0, ): 1, (0, 3): 2})
    assert d.num_binary_variables == 2
Example #22
0
def test_qubo_reinitialize_dictionary():

    d = QUBOMatrix({(0, 0): 1, (1, 0): 2, (2, 0): 0, (0, 1): 1})
    assert d == {(0, ): 1, (0, 1): 3}
Example #23
0
def test_qubo_default_valid():

    d = QUBOMatrix()
    assert d[(0, 0)] == 0
    d[(0, 0)] += 1
    assert d == {(0, ): 1}
Example #24
0
    def to_qubo(self, A=None, B=1):
        r"""to_qubo.

        Create and return the job sequencing problem in QUBO form following
        section 6.3 of [Lucas]. The Q matrix for the QUBO
        will be returned as an uppertriangular dictionary. Thus, the problem
        becomes minimizing :math:`\sum_{i \leq j} x_i x_j Q_{ij}`. A and B are
        parameters to enforce constraints.

        If all the constraints are satisfied, then the objective function will
        be equal to the total length of the scheduling.

        Parameters
        ----------
        A: positive float (optional, defaults to None).
            ``A`` enforces the constraints. If ``A is None``, then ``A`` will
            be chosen such that the minimum of the QUBO is `guaranteed` to
            satisfy the constraints (``A = B*max(L)``). This may not be the
            best value for any particular QUBO solver, since it may cause a non
            smooth landscape that is hard to minimize.
        B: positive float (optional, defaults to 1).
            ``B`` is the constant in front of the portion of the QUBO to
            minimize.

        Return
        ------
        Q : qubovert.utils.QUBOMatrix object.
            The upper triangular QUBO matrix, a QUBOMatrix object.
            For most practical purposes, you can use QUBOMatrix in the
            same way as an ordinary dictionary. For more information,
            see ``help(qubovert.utils.QUBOMatrix)``.

        """
        # all naming conventions follow the paper listed in the docstring

        if A is None:
            A = B * self._max_L

        Q = QUBOMatrix()

        Q += self._N * A  # offset comes from the first constraint

        # encode H_B (equation 55)
        # minimize worker 0's length
        for job, length in self._lengths.items():
            ind = self._x(job, 0)  # worker zero
            Q[(ind, )] += B * length

        # encode H_A (equation 54)

        # enforce that each job is covered exactly once.
        for job in self._lengths:
            for worker in range(self._m):
                ind = self._x(job, worker)
                Q[(ind, )] -= 2 * A
                for workerp in range(self._m):
                    indp = self._x(job, workerp)
                    Q[(ind, indp)] += A

        # enforce worker 0's length is larger than all the other workers'
        # lengths
        max_M = self._log_M if self._log_trick else self._M
        for worker in range(1, self._m):  # exclude worker 0

            for n in range(max_M):
                ind = self._y(n, worker)
                for np in range(max_M):
                    indp = self._y(np, worker)
                    if self._log_trick:
                        Q[(ind, indp)] += A * pow(2, n + np)
                    else:
                        Q[(ind, indp)] += A * (n + 1) * (np + 1)

                for job, length in self._lengths.items():
                    ind1, ind2 = self._x(job, worker), self._x(job, 0)
                    val = 2 * A * length * (pow(2, n)
                                            if self._log_trick else n + 1)
                    Q[(ind, ind1)] += val
                    Q[(ind, ind2)] -= val

            for job, length in self._lengths.items():
                ind1, ind2 = self._x(job, worker), self._x(job, 0)
                for jobp, lengthp in self._lengths.items():
                    ind1p, ind2p = self._x(jobp, worker), self._x(jobp, 0)
                    val = A * length * lengthp
                    Q[(ind1, ind1p)] += val
                    Q[(ind2, ind2p)] += val
                    Q[(ind2, ind1p)] -= val
                    Q[(ind1, ind2p)] -= val

        return Q
Example #25
0
def test_qubo_update():

    d = QUBOMatrix({(0, 0): 1, (0, 1): 2})
    d.update({(0, ): 0, (1, 0): 1, (1, 1): -1})
    assert d == {(0, 1): 1, (1, ): -1}
Example #26
0
def test_qubo_multiplication():

    temp = QUBOMatrix({(0, 0): 1, (0, 1): 2})
    temp += 2

    # __mul__
    d = temp.copy()
    g = d * 3
    assert g == {(0, ): 3, (0, 1): 6, (): 6}

    d = temp.copy()
    g = d * 0
    assert g == {}

    # __imul__
    d = temp.copy()
    d *= 3
    assert d == {(0, ): 3, (0, 1): 6, (): 6}

    d = temp.copy()
    d *= 0
    assert d == {}

    # __rmul__
    d = temp.copy()
    g = 3 * d
    assert g == {(0, ): 3, (0, 1): 6, (): 6}

    d = temp.copy()
    g = 0 * d
    assert g == {}

    # __truediv__
    d = temp.copy()
    g = d / 2
    assert g == {(0, ): .5, (0, 1): 1, (): 1}

    # __itruediv__
    d = temp.copy()
    d /= 2
    assert d == {(0, ): .5, (0, 1): 1, (): 1}

    # __floordiv__
    d = temp.copy()
    g = d // 2
    assert g == {(0, 1): 1, (): 1}

    # __ifloordiv__
    d = temp.copy()
    d //= 2
    assert d == {(0, 1): 1, (): 1}

    # __mul__ but with dict
    d = temp.copy()
    d *= {(1, ): 2, (0, ): -1}
    assert d == {(0, ): -3, (0, 1): 4, (1, ): 4}

    # __pow__
    d = temp.copy()
    d **= 2
    assert d == {(0, ): 5, (0, 1): 16, (): 4}

    temp = d.copy()
    assert d**3 == d * d * d

    # should raise a KeyError since can't fit this into QUBO.
    with assert_raises(KeyError):
        QUBOMatrix({(0, 1): 1, (1, 2): -1})**2