text: # Copyright 2020 D-Wave Systems Inc.
  #
  #    Licensed under the Apache License, Version 2.0 (the "License");
  #    you may not use this file except in compliance with the License.
  #    You may obtain a copy of the License at
  #
  #        http://www.apache.org/licenses/LICENSE-2.0
  #
  #    Unless required by applicable law or agreed to in writing, software
  #    distributed under the License is distributed on an "AS IS" BASIS,
  #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  #    See the License for the specific language governing permissions and
  #    limitations under the License.
  #
  # =============================================================================
  from collections.abc import Sequence, Set
  
  from dimod.bqm.adjvectorbqm import AdjVectorBQM
  from dimod.core.bqm import BQM
  from dimod.vartypes import as_vartype
  
  __all__ = ['as_bqm']
  
  
  def as_bqm(*args, cls=None, copy=False):
      """Convert the input to a binary quadratic model.
  
      Converts the following input formats to a binary quadratic model (BQM):
  
          as_bqm(vartype)
              Creates an empty binary quadratic model.
  
          as_bqm(bqm)
              Creates a BQM from another BQM. See `copy` and `cls` kwargs below.
  
          as_bqm(bqm, vartype)
              Creates a BQM from another BQM, changing to the appropriate
              `vartype` if necessary. See `copy` and `cls` kwargs below.
  
          as_bqm(n, vartype)
              Creates a BQM with `n` variables, indexed linearly from zero,
              setting all biases to zero.
  
          as_bqm(quadratic, vartype)
              Creates a BQM from quadratic biases given as a square array_like_
              or a dictionary of the form `{(u, v): b, ...}`. Note that when
              formed with SPIN-variables, biases on the diagonal are added to the
              offset.
  
          as_bqm(linear, quadratic, vartype)
              Creates a BQM from linear and quadratic biases, where `linear` is a
              one-dimensional array_like_ or a dictionary of the form
              `{v: b, ...}`, and `quadratic` is a square array_like_ or a
              dictionary of the form `{(u, v): b, ...}`. Note that when formed
              with SPIN-variables, biases on the diagonal are added to the offset.
  
          as_bqm(linear, quadratic, offset, vartype)
              Creates a BQM from linear and quadratic biases, where `linear` is a
              one-dimensional array_like_ or a dictionary of the form
              `{v: b, ...}`, and `quadratic` is a square array_like_ or a
              dictionary of the form `{(u, v): b, ...}`, and `offset` is a
              numerical offset. Note that when formed with SPIN-variables, biases
              on the diagonal are added to the offset.
  
      Args:
          *args:
              See above.
  
          cls (type/list, optional):
              Class of the returned BQM. If given as a list,
              the returned BQM is of one of the types in the list. Default is
              :class:`.AdjVectorBQM`.
  
          copy (bool, optional, default=False):
              If False, a new BQM is only constructed when
              necessary.
  
      Returns:
          A binary quadratic model.
  
      .. _array_like: https://docs.scipy.org/doc/numpy/user/basics.creation.html
  
      """
  
      if cls is None:
          if isinstance(args[0], BQM):
              cls = type(args[0])
          else:
              cls = AdjVectorBQM
      elif isinstance(cls, (Sequence, Set)):  # want Collection, but not in 3.5
          classes = tuple(cls)
          if not classes:
              raise ValueError("cls kwarg should be a type or a list of types")
          if type(args[0]) in classes:
              cls = type(args[0])
          else:
              # otherwise just pick the first one
              cls = classes[0]
  
      if isinstance(args[0], cls) and not copy:
          # this is the only case (currently) in which copy matters
          if len(args) == 1:
              return args[0]
          elif len(args) == 2:
              bqm, vartype = args
              if bqm.vartype is as_vartype(vartype):
                  return bqm
              # otherwise we're doing a copy
          # otherwise we don't have a well-formed bqm input so pass off the check
          # to cls(*args)
  
      return cls(*args)
  