r"""Evaluate artifact with agent's current rules and weights.

        :param artifact:
            :class:`~creamas.core.artifact.Artifact` to be evaluated

        :type artifact:
            :py:class:`~creamas.core.artifact.Artifact`

        :returns:
            Agent's evaluation of the artifact, in [-1,1], and framing. In this
            basic implementation framing is always ``None``.

        :rtype:
            tuple

        Actual evaluation formula in this basic implementation is:

        .. math::

            e(A) = \frac{\sum_{i=1}^{n} r_{i}(A)w_i}
            {\sum_{i=1}^{n} \lvert w_i \rvert},

        where :math:`r_{i}(A)` is the :math:`i` th rule's evaluation on
        artifact :math:`A`, and :math:`w_i` is the weight for rule
        :math:`r_i`.

def evaluate(self, artifact):
        r"""Evaluate artifact with agent's current rules and weights.

        :param artifact:
            :class:`~creamas.core.artifact.Artifact` to be evaluated

        :type artifact:
            :py:class:`~creamas.core.artifact.Artifact`

        :returns:
            Agent's evaluation of the artifact, in [-1,1], and framing. In this
            basic implementation framing is always ``None``.

        :rtype:
            tuple

        Actual evaluation formula in this basic implementation is:

        .. math::

            e(A) = \frac{\sum_{i=1}^{n} r_{i}(A)w_i}
            {\sum_{i=1}^{n} \lvert w_i \rvert},

        where :math:`r_{i}(A)` is the :math:`i` th rule's evaluation on
        artifact :math:`A`, and :math:`w_i` is the weight for rule
        :math:`r_i`.
        """
        s = 0
        w = 0.0
        if len(self.R) == 0:
            return 0.0, None

        for i in range(len(self.R)):
            s += self.R[i](artifact) * self.W[i]
            w += abs(self.W[i])

        if w == 0.0:
            return 0.0, None
        return s / w, None