Пример #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})
Пример #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
Пример #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}
Пример #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()
Пример #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
Пример #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
Пример #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}
Пример #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}
Пример #9
0
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)
Пример #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)
Пример #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()}
Пример #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
Пример #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
Пример #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]])
Пример #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
Пример #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)")
Пример #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})
Пример #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
Пример #19
0
def test_qubo_max_index():

    d = QUBOMatrix({(0, 0): 1, (0, 3): 2})
    assert d.max_index == 3
Пример #20
0
def test_num_terms():

    d = QUBOMatrix({(0, ): 1, (0, 3): 2, (0, 2): -1})
    assert d.num_terms == len(d)
Пример #21
0
def test_qubo_num_binary_variables():

    d = QUBOMatrix({(0, ): 1, (0, 3): 2})
    assert d.num_binary_variables == 2
Пример #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}
Пример #23
0
def test_qubo_default_valid():

    d = QUBOMatrix()
    assert d[(0, 0)] == 0
    d[(0, 0)] += 1
    assert d == {(0, ): 1}
Пример #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
Пример #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}
Пример #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