def energy(self, sample):
        """Determine the energy of the specified sample of a binary quadratic model.

        Energy of a sample for a binary quadratic model is defined as a sum, offset
        by the constant energy offset associated with the binary quadratic model, of
        the sample multipled by the linear bias of the variable and
        all its interactions; that is,

        .. math::

            E(\mathbf{s}) = \sum_v h_v s_v + \sum_{u,v} J_{u,v} s_u s_v + c

        where :math:`s_v` is the sample, :math:`h_v` is the linear bias, :math:`J_{u,v}`
        the quadratic bias (interactions), and :math:`c` the energy offset.

        Code for the energy calculation might look like the following::

            energy = model.offset  # doctest: +SKIP
            for v in model:  # doctest: +SKIP
                energy += model.linear[v] * sample[v]
            for u, v in model.quadratic:  # doctest: +SKIP
                energy += model.quadratic[(u, v)] * sample[u] * sample[v]

        Args:
            sample (dict):
                Sample for which to calculate the energy, formatted as a dict where keys
                are variables and values are the value associated with each variable.

        Returns:
            float: Energy for the sample.

        Examples:
            This example creates a binary quadratic model and returns the energies for
            a couple of samples.

            >>> import dimod
            >>> bqm = dimod.BinaryQuadraticModel({1: 1, 2: 1}, {(1, 2): 1}, 0.5, dimod.SPIN)
            >>> bqm.energy({1: -1, 2: -1})
            -0.5
            >>> bqm.energy({1: 1, 2: 1})
            3.5

        """
        linear = self.linear
        quadratic = self.quadratic

        if isinstance(sample, SampleView):
            # because the SampleView object simply reads from an underlying matrix, each read
            # is relatively expensive.
            # However, sample.items() is ~10x faster than {sample[v] for v in sample}, therefore
            # it is much more efficient to dump sample into a dictionary for repeated reads
            sample = dict(sample)

        en = self.offset
        en += sum(linear[v] * sample[v] for v in linear)
        en += sum(sample[u] * sample[v] * quadratic[(u, v)] for u, v in quadratic)
        return en