示例#1
0
    def __init__(self):
        """Creates a new BaseInterface.

        This class is not meant to be instantiated directly nor used
        externally.
        """
        if type(self) == BaseInterface:
            raise TypeError("BaseInterface must be sub-classed")
        self._index = NameIndex()
示例#2
0
    def __init__(self, varindex):
        """Creates a new LinearConstraintInterface.

        The linear constraints interface is exposed by the top-level
        `OptimizationProblem` class as `OptimizationProblem.linear_constraints`.
        This constructor is not meant to be used externally.
        """
        super(LinearConstraintInterface, self).__init__()
        self._rhs = []
        self._senses = []
        self._range_values = []
        self._names = []
        self._lin_expr = []
        self._index = NameIndex()
        self._varindex = varindex
示例#3
0
    def __init__(self):
        """Creates a new VariablesInterface.

        The variables interface is exposed by the top-level `OptimizationProblem` class
        as `OptimizationProblem.variables`.  This constructor is not meant to be used
        externally.
        """
        super(VariablesInterface, self).__init__()
        self._names = []
        self._lb = []
        self._ub = []
        self._types = []
        # self._obj = []
        # self._columns = []
        self._index = NameIndex()
示例#4
0
 def test_name_index2(self):
     a = NameIndex()
     a.build(['1', '2', '3'])
     self.assertEqual(a.convert('1'), 0)
     self.assertListEqual(a.convert(), [0, 1, 2])
     self.assertListEqual(a.convert('1', '3'), [0, 1, 2])
     self.assertListEqual(a.convert('1', '2'), [0, 1])
示例#5
0
class LinearConstraintInterface(BaseInterface):
    """Methods for adding, modifying, and querying linear constraints."""
    def __init__(self, varindex):
        """Creates a new LinearConstraintInterface.

        The linear constraints interface is exposed by the top-level
        `OptimizationProblem` class as `OptimizationProblem.linear_constraints`.
        This constructor is not meant to be used externally.
        """
        super(LinearConstraintInterface, self).__init__()
        self._rhs = []
        self._senses = []
        self._range_values = []
        self._names = []
        self._lin_expr = []
        self._index = NameIndex()
        self._varindex = varindex

    def get_num(self):
        """Returns the number of linear constraints.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c1", "c2", "c3"])
        >>> op.linear_constraints.get_num()
        3
        """
        return len(self._names)

    def add(self,
            lin_expr=None,
            senses="",
            rhs=None,
            range_values=None,
            names=None):
        """Adds linear constraints to the problem.

        linear_constraints.add accepts the keyword arguments lin_expr,
        senses, rhs, range_values, and names.

        If more than one argument is specified, all arguments must
        have the same length.

        lin_expr may be either a list of SparsePair instances or a
        matrix in list-of-lists format.

        Note
          The entries of lin_expr must not contain duplicate indices.
          If an entry of lin_expr references a variable more than
          once, either by index, name, or a combination of index and
          name, an exception will be raised.

        senses must be either a list of single-character strings or a
        string containing the senses of the linear constraints.
        Each entry must
        be one of 'G', 'L', 'E', and 'R', indicating greater-than,
        less-than, equality, and ranged constraints, respectively.

        rhs is a list of floats, specifying the righthand side of
        each linear constraint.

        range_values is a list of floats, specifying the difference
        between lefthand side and righthand side of each linear constraint.
        If range_values[i] > 0 (zero) then the constraint i is defined as
        rhs[i] <= rhs[i] + range_values[i]. If range_values[i] < 0 (zero)
        then constraint i is defined as
        rhs[i] + range_value[i] <= a*x <= rhs[i].

        names is a list of strings.

        Returns an iterator containing the indices of the added linear
        constraints.

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.variables.add(names = ["x1", "x2", "x3"])
        >>> indices = op.linear_constraints.add(\
                lin_expr = [SparsePair(ind = ["x1", "x3"], val = [1.0, -1.0]),\
                            SparsePair(ind = ["x1", "x2"], val = [1.0, 1.0]),\
                            SparsePair(ind = ["x1", "x2", "x3"], val = [-1.0] * 3),\
                            SparsePair(ind = ["x2", "x3"], val = [10.0, -2.0])],\
                senses = ["E", "L", "G", "R"],\
                rhs = [0.0, 1.0, -1.0, 2.0],\
                range_values = [0.0, 0.0, 0.0, -10.0],\
                names = ["c0", "c1", "c2", "c3"])
        >>> op.linear_constraints.get_rhs()
        [0.0, 1.0, -1.0, 2.0]
        """

        arg_list = init_list_args(lin_expr, senses, rhs, range_values, names)
        arg_lengths = [len(x) for x in arg_list]
        if len(arg_lengths) == 0:
            return range(0)
        max_length = max(arg_lengths)
        for arg_length in arg_lengths:
            if arg_length > 0 and arg_length != max_length:
                raise QiskitOptimizationError(
                    "inconsistent arguments in linear_constraints.add().")
        if max_length == 0:
            return range(len(self._names), len(self._names))
        assert max_length > 0

        if not rhs:
            rhs = [0.0] * max_length
        self._rhs.extend(rhs)

        if not senses:
            senses = "E" * max_length
        self._senses.extend(senses)

        if not range_values:
            range_values = [0.0] * max_length
        self._range_values.extend(range_values)

        if not names:
            names = [
                "c" + str(cnt) for cnt in range(len(self._names),
                                                len(self._names) + max_length)
            ]
        self._names.extend(names)
        self._index.build(self._names)

        if not lin_expr:
            lin_expr = [SparsePair()] * max_length
        for sp in lin_expr:
            lin_expr_dict = {}
            if isinstance(sp, SparsePair):
                zip_iter = zip(sp.ind, sp.val)
            elif isinstance(sp, Sequence) and len(sp) == 2:
                zip_iter = zip(sp[0], sp[1])
            else:
                raise QiskitOptimizationError(
                    'Invalid lin_expr: {}'.format(lin_expr))
            for i, val in zip_iter:
                i = self._varindex(i)
                if i in lin_expr_dict:
                    raise QiskitOptimizationError(
                        'Variables should only appear once in linear constraint.'
                    )
                lin_expr_dict[i] = val
            self._lin_expr.append(lin_expr_dict)

        return range(len(self._names) - max_length, len(self._names))

    def delete(self, *args):
        """Removes linear constraints from the problem.

        There are four forms by which linear_constraints.delete may be
        called.

        linear_constraints.delete()
          deletes all linear constraints from the problem.

        linear_constraints.delete(i)
          i must be a linear constraint name or index. Deletes the
          linear constraint whose index or name is i.

        linear_constraints.delete(s)
          s must be a sequence of linear constraint names or indices.
          Deletes the linear constraints with names or indices contained
          within s. Equivalent to [linear_constraints.delete(i) for i in s].

        linear_constraints.delete(begin, end)
          begin and end must be linear constraint indices or linear
          constraint names. Deletes the linear constraints with indices
          between begin and end, inclusive of end. Equivalent to
          linear_constraints.delete(range(begin, end + 1)). This will
          give the best performance when deleting batches of linear
          constraints.

        See CPXdelrows in the Callable Library Reference Manual for
        more detail.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names=[str(i) for i in range(10)])
        >>> op.linear_constraints.get_num()
        10
        >>> op.linear_constraints.delete(8)
        >>> op.linear_constraints.get_names()
        ['0', '1', '2', '3', '4', '5', '6', '7', '9']
        >>> op.linear_constraints.delete("1", 3)
        >>> op.linear_constraints.get_names()
        ['0', '4', '5', '6', '7', '9']
        >>> op.linear_constraints.delete([2, "0", 5])
        >>> op.linear_constraints.get_names()
        ['4', '6', '7']
        >>> op.linear_constraints.delete()
        >>> op.linear_constraints.get_names()
        []
        """
        if len(args) == 0:
            # Delete all
            self._rhs = []
            self._senses = []
            self._names = []
            self._lin_expr = []
            self._range_values = []
            self._index = NameIndex()

        keys = self._index.convert(*args)
        if isinstance(keys, int):
            keys = [keys]
        for i in sorted(keys, reverse=True):
            del self._rhs[i]
            del self._senses[i]
            del self._names[i]
            del self._lin_expr[i]
            del self._range_values[i]
        self._index.build(self._names)

    def set_rhs(self, *args):
        """Sets the righthand side of a set of linear constraints.

        There are two forms by which linear_constraints.set_rhs may be
        called.

        linear_constraints.set_rhs(i, rhs)
          i must be a row name or index and rhs must be a real number.
          Sets the righthand side of the row whose index or name is
          i to rhs.

        linear_constraints.set_rhs(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, rhs) pairs, each
          of which consists of a row name or index and a real
          number.  Sets the righthand side of the specified rows to
          the corresponding values.  Equivalent to
          [linear_constraints.set_rhs(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> op.linear_constraints.get_rhs()
        [0.0, 0.0, 0.0, 0.0]
        >>> op.linear_constraints.set_rhs("c1", 1.0)
        >>> op.linear_constraints.get_rhs()
        [0.0, 1.0, 0.0, 0.0]
        >>> op.linear_constraints.set_rhs([("c3", 2.0), (2, -1.0)])
        >>> op.linear_constraints.get_rhs()
        [0.0, 1.0, -1.0, 2.0]
        """
        def _set(i, v):
            self._rhs[self._index.convert(i)] = v

        self._setter(_set, *args)

    def set_names(self, *args):
        """Sets the name of a linear constraint or set of linear constraints.

        There are two forms by which linear_constraints.set_names may be
        called.

        linear_constraints.set_names(i, name)
          i must be a linear constraint name or index and name must be a
          string.

        linear_constraints.set_names(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, name) pairs,
          each of which consists of a linear constraint name or index and a
          string.  Sets the name of the specified linear constraints to the
          corresponding strings.  Equivalent to
          [linear_constraints.set_names(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> op.linear_constraints.set_names("c1", "second")
        >>> op.linear_constraints.get_names(1)
        'second'
        >>> op.linear_constraints.set_names([("c3", "last"), (2, "middle")])
        >>> op.linear_constraints.get_names()
        ['c0', 'second', 'middle', 'last']
        """
        def _set(i, v):
            self._names[self._index.convert(i)] = v

        self._setter(_set, *args)

    def set_senses(self, *args):
        """Sets the sense of a linear constraint or set of linear constraints.

        There are two forms by which linear_constraints.set_senses may be
        called.

        linear_constraints.set_senses(i, type)
          i must be a row name or index and name must be a
          single-character string.

        linear_constraints.set_senses(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, sense) pairs,
          each of which consists of a row name or index and a
          single-character string.  Sets the sense of the specified
          rows to the corresponding strings.  Equivalent to
          [linear_constraints.set_senses(pair[0], pair[1]) for pair in seq_of_pairs].

        The senses of the constraints must be one of 'G', 'L', 'E',
        and 'R', indicating greater-than, less-than, equality, and
        ranged constraints, respectively.

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> op.linear_constraints.get_senses()
        ['E', 'E', 'E', 'E']
        >>> op.linear_constraints.set_senses("c1", "G")
        >>> op.linear_constraints.get_senses(1)
        'G'
        >>> op.linear_constraints.set_senses([("c3", "L"), (2, "R")])
        >>> op.linear_constraints.get_senses()
        ['E', 'G', 'R', 'L']
        """
        def _set(i, v):
            v = v.upper()
            if v in ["G", "L", "E", "R"]:
                self._senses[self._index.convert(i)] = v
            else:
                raise QiskitOptimizationError("Wrong sense {}".format(v))

        self._setter(_set, *args)

    def set_linear_components(self, *args):
        """Sets a linear constraint or set of linear constraints.

        There are two forms by which this method may be called:

        linear_constraints.set_linear_components(i, lin)
          i must be a row name or index and lin must be either a
          SparsePair or a pair of sequences, the first of which
          consists of variable names or indices, the second of which
          consists of floats.

        linear_constraints.set_linear_components(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, lin) pairs,
          each of which consists of a row name or index and a vector
          as described above.  Sets the specified rows
          to the corresponding vector.  Equivalent to
          [linear_constraints.set_linear_components(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> indices = op.variables.add(names = ["x0", "x1"])
        >>> op.linear_constraints.set_linear_components("c0", [["x0"], [1.0]])
        >>> op.linear_constraints.get_rows("c0")
        SparsePair(ind = [0], val = [1.0])
        >>> op.linear_constraints.set_linear_components([
                                                ("c3", SparsePair(ind = ["x1"], val = [-1.0])),\
                                                (2, [[0, 1], [-2.0, 3.0]])])
        >>> op.linear_constraints.get_rows()
        [SparsePair(ind = [0], val = [1.0]), SparsePair(ind = [], val = []),
        SparsePair(ind = [0, 1], val = [-2.0, 3.0]), SparsePair(ind = [1], val = [-1.0])]
        """
        def _set(i, v):
            if isinstance(v, SparsePair):
                zip_iter = zip(v.ind, v.val)
            elif isinstance(v, Sequence) and len(v) == 2:
                zip_iter = zip(v[0], v[1])
            else:
                raise QiskitOptimizationError(
                    "Wrong linear expression. A SparsePair is expected: {}".
                    format(v))
            i = self._index.convert(i)
            for j, w in zip_iter:
                j = self._varindex(j)
                if w == 0:
                    if j in self._lin_expr[i]:
                        del self._lin_expr[i][j]
                else:
                    self._lin_expr[i][j] = w

        self._setter(_set, *args)

    def set_range_values(self, *args):
        """Sets the range values for a set of linear constraints.

        That is, this method sets the lefthand side (lhs) for each ranged
        constraint of the form lhs <= lin_expr <= rhs.

        The range values are a list of floats, specifying the difference
        between lefthand side and righthand side of each linear constraint.
        If range_values[i] > 0 (zero) then the constraint i is defined as
        rhs[i] <= rhs[i] + range_values[i]. If range_values[i] < 0 (zero)
        then constraint i is defined as
        rhs[i] + range_value[i] <= a*x <= rhs[i].

        Note that changing the range values will not change the sense of a
        constraint; you must call the method set_senses() of the class
        LinearConstraintInterface to change the sense of a ranged row if
        the previous range value was 0 (zero) and the constraint sense was not
        'R'. Similarly, changing the range coefficient from a nonzero value to
        0 (zero) will not change the constraint sense from 'R" to "E"; an
        additional call of setsenses() is required to accomplish that.

        There are two forms by which linear_constraints.set_range_values may be
        called.

        linear_constraints.set_range_values(i, range)
          i must be a row name or index and range must be a real
          number.  Sets the range value of the row whose index or
          name is i to range.

        linear_constraints.set_range_values(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, range) pairs, each
          of which consists of a row name or index and a real
          number.  Sets the range values for the specified rows to
          the corresponding values.  Equivalent to
          [linear_constraints.set_range_values(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> op.linear_constraints.set_range_values("c1", 1.0)
        >>> op.linear_constraints.get_range_values()
        [0.0, 1.0, 0.0, 0.0]
        >>> op.linear_constraints.set_range_values([("c3", 2.0), (2, -1.0)])
        >>> op.linear_constraints.get_range_values()
        [0.0, 1.0, -1.0, 2.0]
        """
        def _set(i, v):
            self._range_values[self._index.convert(i)] = v
            # TODO: raise QiskitOptimizationError("Wrong range!")

        self._setter(_set, *args)

    def set_coefficients(self, *args):
        """Sets individual coefficients of the linear constraint matrix.

        There are two forms by which
        linear_constraints.set_coefficients may be called.

        linear_constraints.set_coefficients(row, col, val)
          row and col must be indices or names of a linear constraint
          and variable, respectively.  The corresponding coefficient
          is set to val.

        linear_constraints.set_coefficients(coefficients)
          coefficients must be a list of (row, col, val) triples as
          described above.

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"])
        >>> indices = op.variables.add(names = ["x0", "x1"])
        >>> op.linear_constraints.set_coefficients("c0", "x1", 1.0)
        >>> op.linear_constraints.get_rows(0)
        SparsePair(ind = [1], val = [1.0])
        >>> op.linear_constraints.set_coefficients([("c2", "x0", 2.0),\
                                                   ("c2", "x1", -1.0)])
        >>> op.linear_constraints.get_rows("c2")
        SparsePair(ind = [0, 1], val = [2.0, -1.0])
        """
        if len(args) == 3:
            arg_list = [args]
        elif len(args) == 1 and isinstance(args[0], Sequence):
            arg_list = args[0]
        else:
            raise QiskitOptimizationError("Invalid arguments {}".format(args))
        for i, j, v in arg_list:
            i = self._index.convert(i)
            j = self._varindex(j)
            if v == 0:
                if j in self._lin_expr[i]:
                    del self._lin_expr[i][j]
            else:
                self._lin_expr[i][j] = v

    def get_rhs(self, *args):
        """Returns the righthand side of constraints from the problem.

        Can be called by four forms.

        linear_constraints.get_rhs()
          return the righthand side of all linear constraints from
          the problem.

        linear_constraints.get_rhs(i)
          i must be a linear constraint name or index.  Returns the
          righthand side of the linear constraint whose index or
          name is i.

        linear_constraints.get_rhs(s)
          s must be a sequence of linear constraint names or indices.
          Returns the righthand side of the linear constraints with
          indices the members of s.  Equivalent to
          [linear_constraints.get_rhs(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(rhs = [1.5 * i for i in range(10)],\
                                     names = [str(i) for i in range(10)])
        >>> op.linear_constraints.get_num()
        10
        >>> op.linear_constraints.get_rhs(8)
        12.0
        >>> op.linear_constraints.get_rhs([2,"0",5])
        [3.0, 0.0, 7.5]
        >>> op.linear_constraints.get_rhs()
        [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0, 13.5]
        """
        def _get(i):
            return self._rhs[i]

        if len(args) == 0:
            return copy.deepcopy(self._rhs)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_senses(self, *args):
        """Returns the senses of constraints from the problem.

        Can be called by four forms.

        linear_constraints.get_senses()
          return the senses of all linear constraints from the
          problem.

        linear_constraints.get_senses(i)
          i must be a linear constraint name or index.  Returns the
          sense of the linear constraint whose index or name is i.

        linear_constraints.get_senses(s)
          s must be a sequence of linear constraint names or indices.
          Returns the senses of the linear constraints with indices
          the members of s.  Equivalent to
          [linear_constraints.get_senses(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(
        ...     senses=["E", "G", "L", "R"],
        ...     names=[str(i) for i in range(4)])
        >>> op.linear_constraints.get_num()
        4
        >>> op.linear_constraints.get_senses(1)
        'G'
        >>> op.linear_constraints.get_senses("1",3)
        ['G', 'L', 'R']
        >>> op.linear_constraints.get_senses([2,"0",1])
        ['L', 'E', 'G']
        >>> op.linear_constraints.get_senses()
        ['E', 'G', 'L', 'R']
        """
        def _get(i):
            return self._senses[i]

        if len(args) == 0:
            return copy.deepcopy(self._senses)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_range_values(self, *args):
        """Returns the range values of linear constraints from the problem.

        That is, this method returns the lefthand side (lhs) for each
        ranged constraint of the form lhs <= lin_expr <= rhs. This method
        makes sense only for ranged constraints, that is, linear constraints
        of sense 'R'.

        The range values are a list of floats, specifying the difference
        between lefthand side and righthand side of each linear constraint.
        If range_values[i] > 0 (zero) then the constraint i is defined as
        rhs[i] <= rhs[i] + range_values[i]. If range_values[i] < 0 (zero)
        then constraint i is defined as
        rhs[i] + range_value[i] <= a*x <= rhs[i].

        Can be called by four forms.

        linear_constraints.get_range_values()
          return the range values of all linear constraints from the
          problem.

        linear_constraints.get_range_values(i)
          i must be a linear constraint name or index.  Returns the
          range value of the linear constraint whose index or name is i.

        linear_constraints.get_range_values(s)
          s must be a sequence of linear constraint names or indices.
          Returns the range values of the linear constraints with
          indices the members of s.  Equivalent to
          [linear_constraints.get_range_values(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(\
                range_values = [1.5 * i for i in range(10)],\
                senses = ["R"] * 10,\
                names = [str(i) for i in range(10)])
        >>> op.linear_constraints.get_num()
        10
        >>> op.linear_constraints.get_range_values(8)
        12.0
        >>> op.linear_constraints.get_range_values("1",3)
        [1.5, 3.0, 4.5]
        >>> op.linear_constraints.get_range_values([2,"0",5])
        [3.0, 0.0, 7.5]
        >>> op.linear_constraints.get_range_values()
        [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0, 13.5]
        """
        def _get(i):
            return self._range_values[i]

        if len(args) == 0:
            return copy.deepcopy(self._range_values)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_coefficients(self, *args):
        """Returns coefficients by row, column coordinates.

        There are three forms by which
        linear_constraints.get_coefficients may be called.

        Without arguments, it returns a dictionary indexed
        first by constraints and second by variables.

        With two arguments,
        linear_constraints.get_coefficients(row, col)
          returns the coefficient.

        With one argument,
        linear_constraints.get_coefficients(sequence_of_pairs)
          returns a list of coefficients.

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.variables.add(names = ["x0", "x1"])
        >>> indices = op.linear_constraints.add(\
                names = ["c0", "c1"],\
                lin_expr = [[[1], [1.0]], [[0, 1], [2.0, -1.0]]])
        >>> op.linear_constraints.get_coefficients("c0", "x1")
        1.0
        >>> op.linear_constraints.get_coefficients([("c1", "x0"), ("c1", "x1")])
        [2.0, -1.0]
        """
        def _get(args):
            i, j = args
            return self._lin_expr[i].get(j, 0)

        if len(args) == 0:
            return copy.deepcopy(self._lin_expr)
        elif len(args) == 1 and isinstance(args[0], Sequence):
            i, j = zip(*args[0])
            i = self._index.convert(i)
            j = self._varindex(j)
            return self._getter(_get, *zip(i, j))
        elif len(args) == 2:
            i, j = args
            i = self._index.convert(i)
            j = self._varindex(j)
            return _get((i, j))
        else:
            raise QiskitOptimizationError(
                "Wrong number of arguments. Please use 2 or one list of pairs: {}"
                .format(args))

    def get_rows(self, *args):
        """Returns a set of rows of the linear constraint matrix.

        Returns a list of SparsePair instances or a single SparsePair
        instance, depending on the form by which it was called.

        There are four forms by which linear_constraints.get_rows may be called.

        linear_constraints.get_rows()
          return the entire linear constraint matrix.

        linear_constraints.get_rows(i)
          i must be a row name or index.  Returns the ith row of
          the linear constraint matrix.

        linear_constraints.get_rows(s)
          s must be a sequence of row names or indices.  Returns the
          rows of the linear constraint matrix indexed by the members
          of s.  Equivalent to
          [linear_constraints.get_rows(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.variables.add(names = ["x1", "x2", "x3"])
        >>> indices = op.linear_constraints.add(\
                names = ["c0", "c1", "c2", "c3"],\
                lin_expr = [SparsePair(ind = ["x1", "x3"], val = [1.0, -1.0]),\
                            SparsePair(ind = ["x1", "x2"], val = [1.0, 1.0]),\
                            SparsePair(ind = ["x1", "x2", "x3"], val = [-1.0] * 3),\
                            SparsePair(ind = ["x2", "x3"], val = [10.0, -2.0])])
        >>> op.linear_constraints.get_rows(0)
        SparsePair(ind = [0, 2], val = [1.0, -1.0])
        >>> op.linear_constraints.get_rows(["c2", 0])
        [SparsePair(ind = [0, 1, 2], val = [-1.0, -1.0, -1.0]),
          SparsePair(ind = [0, 2], val = [1.0, -1.0])]
        >>> op.linear_constraints.get_rows()
        [
          SparsePair(ind = [0, 2], val = [1.0, -1.0]),
          SparsePair(ind = [0, 1], val = [1.0, 1.0]),
          SparsePair(ind = [0, 1, 2], val = [-1.0, -1.0, -1.0]),
          SparsePair(ind = [1, 2], val = [10.0, -2.0])
        ]
        """
        def _get(i):
            keys = list(self._lin_expr[i].keys())
            keys.sort()
            return SparsePair(keys, [self._lin_expr[i][k] for k in keys])

        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_num_nonzeros(self):
        """Returns the number of nonzeros in the linear constraint matrix.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.variables.add(names = ["x1", "x2", "x3"])
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2", "c3"],\
                                    lin_expr = [SparsePair(ind = ["x1", "x3"], val = [1.0, -1.0]),\
                                            SparsePair(ind = ["x1", "x2"], val = [1.0, 1.0]),\
                                            SparsePair(ind = ["x1", "x2", "x3"], val = [-1.0] * 3),\
                                            SparsePair(ind = ["x2", "x3"], val = [10.0, -2.0])])
        >>> op.linear_constraints.get_num_nonzeros()
        9
        """
        nnz = 0
        for c in self._lin_expr:
            for e in c.values():
                if e != 0.0:
                    nnz += 1
        return nnz

    def get_names(self, *args):
        """Returns the names of linear constraints from the problem.

        There are four forms by which linear_constraints.get_names may be called.

        linear_constraints.get_names()
          return the names of all linear constraints from the problem.

        linear_constraints.get_names(i)
          i must be a linear constraint index.  Returns the name of row i.

        linear_constraints.get_names(s)
          s must be a sequence of row indices.  Returns the names of
          the linear constraints with indices the members of s.
          Equivalent to [linear_constraints.get_names(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c" + str(i) for i in range(10)])
        >>> op.linear_constraints.get_num()
        10
        >>> op.linear_constraints.get_names(8)
        'c8'
        >>> op.linear_constraints.get_names([2, 0, 5])
        ['c2', 'c0', 'c5']
        >>> op.linear_constraints.get_names()
        ['c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9']
        """
        def _get(i):
            return self._names[i]

        if len(args) == 0:
            return self._names
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_histogram(self):
        raise NotImplementedError("histrogram is not implemented")
示例#6
0
    def delete(self, *args):
        """Removes linear constraints from the problem.

        There are four forms by which linear_constraints.delete may be
        called.

        linear_constraints.delete()
          deletes all linear constraints from the problem.

        linear_constraints.delete(i)
          i must be a linear constraint name or index. Deletes the
          linear constraint whose index or name is i.

        linear_constraints.delete(s)
          s must be a sequence of linear constraint names or indices.
          Deletes the linear constraints with names or indices contained
          within s. Equivalent to [linear_constraints.delete(i) for i in s].

        linear_constraints.delete(begin, end)
          begin and end must be linear constraint indices or linear
          constraint names. Deletes the linear constraints with indices
          between begin and end, inclusive of end. Equivalent to
          linear_constraints.delete(range(begin, end + 1)). This will
          give the best performance when deleting batches of linear
          constraints.

        See CPXdelrows in the Callable Library Reference Manual for
        more detail.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = qiskit.optimization.OptimizationProblem()
        >>> indices = op.linear_constraints.add(names=[str(i) for i in range(10)])
        >>> op.linear_constraints.get_num()
        10
        >>> op.linear_constraints.delete(8)
        >>> op.linear_constraints.get_names()
        ['0', '1', '2', '3', '4', '5', '6', '7', '9']
        >>> op.linear_constraints.delete("1", 3)
        >>> op.linear_constraints.get_names()
        ['0', '4', '5', '6', '7', '9']
        >>> op.linear_constraints.delete([2, "0", 5])
        >>> op.linear_constraints.get_names()
        ['4', '6', '7']
        >>> op.linear_constraints.delete()
        >>> op.linear_constraints.get_names()
        []
        """
        if len(args) == 0:
            # Delete all
            self._rhs = []
            self._senses = []
            self._names = []
            self._lin_expr = []
            self._range_values = []
            self._index = NameIndex()

        keys = self._index.convert(*args)
        if isinstance(keys, int):
            keys = [keys]
        for i in sorted(keys, reverse=True):
            del self._rhs[i]
            del self._senses[i]
            del self._names[i]
            del self._lin_expr[i]
            del self._range_values[i]
        self._index.build(self._names)
示例#7
0
 def test_name_index3(self):
     a = NameIndex()
     with self.assertRaises(QiskitOptimizationError):
         a.convert({})
     with self.assertRaises(QiskitOptimizationError):
         a.convert(1, 2, 3)
示例#8
0
class BaseInterface(object):
    """Common methods for sub-interfaces within Qiskit Optimization."""

    def __init__(self):
        """Creates a new BaseInterface.

        This class is not meant to be instantiated directly nor used
        externally.
        """
        if type(self) == BaseInterface:
            raise TypeError("BaseInterface must be sub-classed")
        self._index = NameIndex()

    def get_indices(self, *name) -> Union[int, List[int]]:
        """Converts from names to indices.

        If name is a string, get_indices returns the index of the
        object with that name.  If no such object exists, an
        exception is raised.

        If name is a sequence of strings, get_indices returns a list
        of the indices corresponding to the strings in name.
        Equivalent to map(self.get_indices, name).

        See `NameIndex.convert` for details.

        If the subclass does not provide an index function (i.e., the
        interface is not indexed), then a NotImplementedError is raised.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names=["a", "b"])
        >>> op.variables.get_indices("a")
        0
        >>> op.variables.get_indices(["a", "b"])
        [0, 1]
        """
        return self._index.convert(*name)

    @staticmethod
    def _setter(setfunc: Callable[[Union[str, int], Any], None], *args) -> None:
        """A generic setter method

        Args:
            setfunc(index, val): A setter function of two parameters: `index` and `val`.
                Since `index` can be a string, users need to convert it into an appropriate index
                by applying `NameIndex.convert`.
            *args: A pair of index and value or a list of pairs of index and value.
                `setfunc` is invoked with `args`.

        Returns:
            None
        """
        # check for all elements in args whether they are types
        if len(args) == 1 and \
                all(isinstance(pair, Sequence) and len(pair) == 2 for pair in args[0]):
            for pair in args[0]:
                setfunc(*pair)
        elif len(args) == 2:
            setfunc(*args)
        else:
            raise QiskitOptimizationError("Invalid arguments: {}".format(args))

    @staticmethod
    def _getter(getfunc: Callable[[int], Any], *args) -> Any:
        """A generic getter method

        Args:
            getfunc(index): A getter function with an argument `index`.
                `index` should be already converted by `NameIndex.convert`.
            *args: A single index or a list of indices. `getfunc` is invoked with args.

        Returns: if `args` is a single index, this returns a single value genereted by `getfunc`.
            If `args` is a list of indices, this returns a list of values.
        """
        if len(args) == 0:
            raise QiskitOptimizationError('Empty arguments should be handled in the caller')
        if len(args) == 1:
            if isinstance(args[0], Sequence):
                args = args[0]
            else:
                return getfunc(args[0])
        return [getfunc(k) for k in args]
示例#9
0
class VariablesInterface(BaseInterface):
    """Methods for adding, querying, and modifying variables.

    Example usage:

    >>> from qiskit.optimization import OptimizationProblem
    >>> op = OptimizationProblem()
    >>> indices = op.variables.add(names = ["x0", "x1", "x2"])
    >>> # default values for lower_bounds are 0.0
    >>> op.variables.get_lower_bounds()
    [0.0, 0.0, 0.0]
    >>> # values can be set either one at a time or many at a time
    >>> op.variables.set_lower_bounds(0, 1.0)
    >>> op.variables.set_lower_bounds([("x1", -1.0), (2, 3.0)])
    >>> # values can be queried as a range
    >>> op.variables.get_lower_bounds(0, "x1")
    [1.0, -1.0]
    >>> # values can be queried as a sequence in arbitrary order
    >>> op.variables.get_lower_bounds(["x1", "x2", 0])
    [-1.0, 3.0, 1.0]
    >>> # can query the number of variables
    >>> op.variables.get_num()
    3
    >>> op.variables.set_types(0, op.variables.type.binary)
    >>> op.variables.get_num_binary()
    1
    """

    type = VarTypes()
    """See `VarTypes()` """
    def __init__(self):
        """Creates a new VariablesInterface.

        The variables interface is exposed by the top-level `OptimizationProblem` class
        as `OptimizationProblem.variables`.  This constructor is not meant to be used
        externally.
        """
        super(VariablesInterface, self).__init__()
        self._names = []
        self._lb = []
        self._ub = []
        self._types = []
        # self._obj = []
        # self._columns = []
        self._index = NameIndex()

    def get_num(self):
        """Returns the number of variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.continuous, t.binary, t.integer])
        >>> op.variables.get_num()
        3
        """
        return len(self._names)

    def get_num_continuous(self):
        """Returns the number of continuous variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.continuous, t.binary, t.integer])
        >>> op.variables.get_num_continuous()
        1
        """
        return self._types.count(VarTypes.continuous)

    def get_num_integer(self):
        """Returns the number of integer variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.continuous, t.binary, t.integer])
        >>> op.variables.get_num_integer()
        1
        """
        return self._types.count(VarTypes.integer)

    def get_num_binary(self):
        """Returns the number of binary variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.semi_continuous, t.binary, t.integer])
        >>> op.variables.get_num_binary()
        1
        """
        return self._types.count(VarTypes.binary)

    def get_num_semicontinuous(self):
        """Returns the number of semi-continuous variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.semi_continuous, t.semi_integer, t.semi_integer])
        >>> op.variables.get_num_semicontinuous()
        1
        """
        return self._types.count(VarTypes.semi_continuous)

    def get_num_semiinteger(self):
        """Returns the number of semi-integer variables in the problem.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.semi_continuous, t.semi_integer, t.semi_integer])
        >>> op.variables.get_num_semiinteger()
        2
        """
        return self._types.count(VarTypes.semi_integer)

    def add(self,
            obj=None,
            lb=None,
            ub=None,
            types="",
            names=None,
            columns=None):
        """Adds variables and related data to the problem.

        variables.add accepts the keyword arguments obj, lb, ub, types, names, and columns.

        If more than one argument is specified, all arguments must have the same length.

        Note
            `obj` and `columns` have not been supported yet.
            Use `objective` and `linear_constraint` instead.

        Args:
            obj: a list of floats specifying the linear objective coefficients of the variables.

            lb: a list of floats specifying the lower bounds on the variables.

            ub: a list of floats specifying the upper bounds on the variables.

            types: must be either a list of single-character strings or a string containing
                the types of the variables.

                Note
                    If types is specified, the problem type will be a MIP, even if all variables are
                    specified to be continuous.

            names: a list of strings.

            columns: may be either a list of sparse vectors or a matrix in list-of-lists format.

                Note
                  The entries of columns must not contain duplicate indices.
                  If an entry of columns references a row more than once,
                  either by index, name, or a combination of index and name,
                  an exception will be raised.

        Returns:
            an iterator containing the indices of the added variables.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> from cplex import SparsePair, infinity
        >>> op = OptimizationProblem()
        >>> indices = op.linear_constraints.add(names = ["c0", "c1", "c2"])
        >>> indices = op.variables.add(obj = [1.0, 2.0, 3.0],\
                                      types = [op.variables.type.integer] * 3)
        >>> indices = op.variables.add(obj = [1.0, 2.0, 3.0],\
                                      lb = [-1.0, 1.0, 0.0],\
                                      ub = [100.0, infinity, infinity],\
                                      types = [op.variables.type.integer] * 3,\
                                      names = ["0", "1", "2"],\
                                      columns = [SparsePair(ind = ['c0', 2], val = [1.0, -1.0]),\
                                      [['c2'],[2.0]],\
                                      SparsePair(ind = [0, 1], val = [3.0, 4.0])])

        >>> op.variables.get_lower_bounds()
        [0.0, 0.0, 0.0, -1.0, 1.0, 0.0]
        >>> op.variables.get_cols("1")
        SparsePair(ind = [2], val = [2.0])
        """
        if obj:
            raise QiskitOptimizationError(
                "Please use ObjectiveInterface instead of obj.")
        if columns:
            raise QiskitOptimizationError(
                "Please use LinearConstraintInterface instead of columns.")

        arg_list = init_list_args(lb, ub, types, names)
        arg_lengths = [len(x) for x in arg_list]
        if len(arg_lengths) == 0:
            return range(0)
        max_length = max(arg_lengths)
        for arg_length in arg_lengths:
            if arg_length > 0 and arg_length != max_length:
                raise QiskitOptimizationError("inconsistent arguments")

        if not lb:
            lb = [0.0] * max_length
        self._lb.extend(lb)

        if not ub:
            ub = [infinity] * max_length
        self._ub.extend(ub)

        if not types:
            types = [VarTypes.continuous] * max_length
        for i, t in enumerate(types):
            if t == VarTypes.binary:
                self._ub[i] = 1.0
        self._types.extend(types)

        if not names:
            names = [
                "x" + str(cnt) for cnt in range(len(self._names),
                                                len(self._names) + max_length)
            ]
        self._names.extend(names)
        self._index.build(self._names)

        return range(len(self._names) - max_length, len(self._names))

    def delete(self, *args):
        """Deletes variables from the problem.

        There are four forms by which variables.delete may be called.

        variables.delete()
          deletes all variables from the problem.

        variables.delete(i)
          i must be a variable name or index. Deletes the variable
          whose index or name is i.

        variables.delete(s)
          s must be a sequence of variable names or indices. Deletes
          the variables with names or indices contained within s.
          Equivalent to [variables.delete(i) for i in s].

        variables.delete(begin, end)
          begin and end must be variable indices or variable names.
          Deletes the variables with indices between begin and end,
          inclusive of end. Equivalent to
          variables.delete(range(begin, end + 1)). This will give the
          best performance when deleting batches of variables.

        See CPXdelcols in the Callable Library Reference Manual for
        more detail.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names=[str(i) for i in range(10)])
        >>> op.variables.get_num()
        10
        >>> op.variables.delete(8)
        >>> op.variables.get_names()
        ['0', '1', '2', '3', '4', '5', '6', '7', '9']
        >>> op.variables.delete("1", 3)
        >>> op.variables.get_names()
        ['0', '4', '5', '6', '7', '9']
        >>> op.variables.delete([2, "0", 5])
        >>> op.variables.get_names()
        ['4', '6', '7']
        >>> op.variables.delete()
        >>> op.variables.get_names()
        []
        """
        def _delete(i):
            del self._names[i]
            del self._ub[i]
            del self._lb[i]
            del self._types[i]

        if len(args) == 0:
            # Delete all
            self._names = []
            self._ub = []
            self._lb = []
            self._types = []
            # self._columns = []
            self._index = NameIndex()

        keys = self._index.convert(*args)
        if isinstance(keys, int):
            keys = [keys]
        for i in sorted(keys, reverse=True):
            _delete(i)
        self._index.build(self._names)

    def set_lower_bounds(self, *args):
        """Sets the lower bound for a variable or set of variables.

        There are two forms by which variables.set_lower_bounds may be
        called.

        variables.set_lower_bounds(i, lb)
          i must be a variable name or index and lb must be a real
          number.  Sets the lower bound of the variable whose index
          or name is i to lb.

        variables.set_lower_bounds(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, lb) pairs, each
          of which consists of a variable name or index and a real
          number.  Sets the lower bound of the specified variables to
          the corresponding values.  Equivalent to
          [variables.set_lower_bounds(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names = ["x0", "x1", "x2"])
        >>> op.variables.set_lower_bounds(0, 1.0)
        >>> op.variables.get_lower_bounds()
        [1.0, 0.0, 0.0]
        >>> op.variables.set_lower_bounds([(2, 3.0), ("x1", -1.0)])
        >>> op.variables.get_lower_bounds()
        [1.0, -1.0, 3.0]
        """
        def _set(i, v):
            self._lb[self._index.convert(i)] = v

        self._setter(_set, *args)

    def set_upper_bounds(self, *args):
        """Sets the upper bound for a variable or set of variables.

        There are two forms by which variables.set_upper_bounds may be
        called.

        variables.set_upper_bounds(i, ub)
          i must be a variable name or index and ub must be a real
          number.  Sets the upper bound of the variable whose index
          or name is i to ub.

        variables.set_upper_bounds(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, ub) pairs, each
          of which consists of a variable name or index and a real
          number.  Sets the upper bound of the specified variables to
          the corresponding values.  Equivalent to
          [variables.set_upper_bounds(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names = ["x0", "x1", "x2"])
        >>> op.variables.set_upper_bounds(0, 1.0)
        >>> op.variables.set_upper_bounds([("x1", 10.0), (2, 3.0)])
        >>> op.variables.get_upper_bounds()
        [1.0, 10.0, 3.0]
        """
        def _set(i, v):
            self._ub[self._index.convert(i)] = v

        self._setter(_set, *args)

    def set_names(self, *args):
        """Sets the name of a variable or set of variables.

        There are two forms by which variables.set_names may be
        called.

        variables.set_names(i, name)
          i must be a variable name or index and name must be a
          string.

        variables.set_names(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, name) pairs,
          each of which consists of a variable name or index and a
          string.  Sets the name of the specified variables to the
          corresponding strings.  Equivalent to
          [variables.set_names(pair[0], pair[1]) for pair in seq_of_pairs].

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(types = [t.continuous, t.binary, t.integer])
        >>> op.variables.set_names(0, "first")
        >>> op.variables.set_names([(2, "third"), (1, "second")])
        >>> op.variables.get_names()
        ['first', 'second', 'third']
        """
        def _set(i, v):
            self._names[self._index.convert(i)] = v

        self._setter(_set, *args)
        self._index.build(self._names)

    def set_types(self, *args):
        """Sets the type of a variable or set of variables.

        There are two forms by which variables.set_types may be
        called.

        variables.set_types(i, type)
          i must be a variable name or index and name must be a
          single-character string.

        variables.set_types(seq_of_pairs)
          seq_of_pairs must be a list or tuple of (i, type) pairs,
          each of which consists of a variable name or index and a
          single-character string.  Sets the type of the specified
          variables to the corresponding strings.  Equivalent to
          [variables.set_types(pair[0], pair[1]) for pair in seq_of_pairs].

        Note
          If the types are set, the problem will be treated as a MIP,
          even if all variable types are continuous.

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names = [str(i) for i in range(5)])
        >>> op.variables.set_types(0, op.variables.type.continuous)
        >>> op.variables.set_types([("1", op.variables.type.integer),\
                                   ("2", op.variables.type.binary),\
                                   ("3", op.variables.type.semi_continuous),\
                                   ("4", op.variables.type.semi_integer)])
        >>> op.variables.get_types()
        ['C', 'I', 'B', 'S', 'N']
        >>> op.variables.type[op.variables.get_types(0)]
        'continuous'
        """
        def _set(i, v):
            if v not in [
                    CPX_CONTINUOUS, CPX_BINARY, CPX_INTEGER, CPX_SEMICONT,
                    CPX_SEMIINT
            ]:
                raise QiskitOptimizationError(
                    "Second argument must be a string, as per VarTypes constants."
                )
            self._types[self._index.convert(i)] = v

        self._setter(_set, *args)

    def get_lower_bounds(self, *args):
        """Returns the lower bounds on variables from the problem.

        There are four forms by which variables.get_lower_bounds may be called.

        variables.get_lower_bounds()
          return the lower bounds on all variables from the problem.

        variables.get_lower_bounds(i)
          i must be a variable name or index.  Returns the lower
          bound on the variable whose index or name is i.

        variables.get_lower_bounds(s)
          s must be a sequence of variable names or indices.  Returns
          the lower bounds on the variables with indices the members
          of s.  Equivalent to
          [variables.get_lower_bounds(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(lb = [1.5 * i for i in range(10)],\
                                      names = [str(i) for i in range(10)])
        >>> op.variables.get_num()
        10
        >>> op.variables.get_lower_bounds(8)
        12.0
        >>> op.variables.get_lower_bounds("1",3)
        [1.5, 3.0, 4.5]
        >>> op.variables.get_lower_bounds([2,"0",5])
        [3.0, 0.0, 7.5]
        >>> op.variables.get_lower_bounds()
        [0.0, 1.5, 3.0, 4.5, 6.0, 7.5, 9.0, 10.5, 12.0, 13.5]
        """
        def _get(i):
            return self._lb[i]

        if len(args) == 0:
            return copy.deepcopy(self._lb)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_upper_bounds(self, *args):
        """Returns the upper bounds on variables from the problem.

        There are four forms by which variables.get_upper_bounds may be called.

        variables.get_upper_bounds()
          return the upper bounds on all variables from the problem.

        variables.get_upper_bounds(i)
          i must be a variable name or index.  Returns the upper
          bound on the variable whose index or name is i.

        variables.get_upper_bounds(s)
          s must be a sequence of variable names or indices.  Returns
          the upper bounds on the variables with indices the members
          of s.  Equivalent to
          [variables.get_upper_bounds(i) for i in s]

        variables.get_upper_bounds(begin, end)
          begin and end must be variable indices or variable names.
          Returns the upper bounds on the variables with indices between
          begin and end, inclusive of end. Equivalent to
          variables.get_upper_bounds(range(begin, end + 1)).

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(ub = [(1.5 * i) + 1.0 for i in range(10)],\
                                      names = [str(i) for i in range(10)])
        >>> op.variables.get_num()
        10
        >>> op.variables.get_upper_bounds(8)
        13.0
        >>> op.variables.get_upper_bounds("1",3)
        [2.5, 4.0, 5.5]
        >>> op.variables.get_upper_bounds([2,"0",5])
        [4.0, 1.0, 8.5]
        >>> op.variables.get_upper_bounds()
        [1.0, 2.5, 4.0, 5.5, 7.0, 8.5, 10.0, 11.5, 13.0, 14.5]
        """
        def _get(i):
            return self._ub[i]

        if len(args) == 0:
            return copy.deepcopy(self._ub)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_names(self, *args):
        """Returns the names of variables from the problem.

        There are four forms by which variables.get_names may be called.

        variables.get_names()
          return the names of all variables from the problem.

        variables.get_names(i)
          i must be a variable index.  Returns the name of variable i.

        variables.get_names(s)
          s must be a sequence of variable indices.  Returns the
          names of the variables with indices the members of s.
          Equivalent to [variables.get_names(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names = ['x' + str(i) for i in range(10)])
        >>> op.variables.get_num()
        10
        >>> op.variables.get_names(8)
        'x8'
        >>> op.variables.get_names(1,3)
        ['x1', 'x2', 'x3']
        >>> op.variables.get_names([2,0,5])
        ['x2', 'x0', 'x5']
        >>> op.variables.get_names()
        ['x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9']
        """
        def _get(i):
            return self._names[i]

        if len(args) == 0:
            return copy.deepcopy(self._names)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_types(self, *args):
        """Returns the types of variables from the problem.

        There are four forms by which variables.types may be called.

        variables.types()
          return the types of all variables from the problem.

        variables.types(i)
          i must be a variable name or index.  Returns the type of
          the variable whose index or name is i.

        variables.types(s)
          s must be a sequence of variable names or indices.  Returns
          the types of the variables with indices the members of s.
          Equivalent to [variables.get_types(i) for i in s]

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> t = op.variables.type
        >>> indices = op.variables.add(names = [str(i) for i in range(5)],\
                                      types = [t.continuous, t.integer,\
                                      t.binary, t.semi_continuous, t.semi_integer])
        >>> op.variables.get_num()
        5
        >>> op.variables.get_types(3)
        'S'
        >>> op.variables.get_types(1,3)
        ['I', 'B', 'S']
        >>> op.variables.get_types([2,0,4])
        ['B', 'C', 'N']
        >>> op.variables.get_types()
        ['C', 'I', 'B', 'S', 'N']
        """
        def _get(i):
            return self._types[i]

        if len(args) == 0:
            return copy.deepcopy(self._types)
        keys = self._index.convert(*args)
        return self._getter(_get, keys)

    def get_cols(self, *args):
        raise NotImplementedError(
            "Please use LinearConstraintInterface instead.")

    def get_obj(self, *args):
        raise NotImplementedError("Please use ObjectiveInterface instead.")
示例#10
0
    def delete(self, *args):
        """Deletes variables from the problem.

        There are four forms by which variables.delete may be called.

        variables.delete()
          deletes all variables from the problem.

        variables.delete(i)
          i must be a variable name or index. Deletes the variable
          whose index or name is i.

        variables.delete(s)
          s must be a sequence of variable names or indices. Deletes
          the variables with names or indices contained within s.
          Equivalent to [variables.delete(i) for i in s].

        variables.delete(begin, end)
          begin and end must be variable indices or variable names.
          Deletes the variables with indices between begin and end,
          inclusive of end. Equivalent to
          variables.delete(range(begin, end + 1)). This will give the
          best performance when deleting batches of variables.

        See CPXdelcols in the Callable Library Reference Manual for
        more detail.

        Example usage:

        >>> from qiskit.optimization import OptimizationProblem
        >>> op = OptimizationProblem()
        >>> indices = op.variables.add(names=[str(i) for i in range(10)])
        >>> op.variables.get_num()
        10
        >>> op.variables.delete(8)
        >>> op.variables.get_names()
        ['0', '1', '2', '3', '4', '5', '6', '7', '9']
        >>> op.variables.delete("1", 3)
        >>> op.variables.get_names()
        ['0', '4', '5', '6', '7', '9']
        >>> op.variables.delete([2, "0", 5])
        >>> op.variables.get_names()
        ['4', '6', '7']
        >>> op.variables.delete()
        >>> op.variables.get_names()
        []
        """
        def _delete(i):
            del self._names[i]
            del self._ub[i]
            del self._lb[i]
            del self._types[i]

        if len(args) == 0:
            # Delete all
            self._names = []
            self._ub = []
            self._lb = []
            self._types = []
            # self._columns = []
            self._index = NameIndex()

        keys = self._index.convert(*args)
        if isinstance(keys, int):
            keys = [keys]
        for i in sorted(keys, reverse=True):
            _delete(i)
        self._index.build(self._names)