text: import tensorflow as tf
  from openrec.tf1.legacy.modules.interactions import PairwiseLog
  
  
  class PairwiseEuDist(PairwiseLog):
  
      """
      The PairwiseEuDist module minimizes the weighted pairwise euclidean distance-based hinge loss [cml]_ as follows (regularization and bias terms \
      are not included):
      
      .. math::
          \min \sum_{(i, p, n)} w_{ip} [m + \lVert c(u_i)-c(v_p) \lVert^2 - \lVert c(u_i)-c(v_n) \lVert^2]_+
  
      where :math:`c(x) = \\frac{x}{\max(\lVert x \lVert, 1.0)}`; :math:`u_i` denotes the representation for user :math:`i`; :math:`v_p` and :math:`v_n` denote representations for \
      *positive item* :math:`p` and *negative item* :math:`n`, respectively.
  
      Parameters
      ----------
      user: Tensorflow tensor
          Representations for users involved in the interactions. Shape: **[number of interactions, dimensionality of \
          user representations]**.
      item: Tensorflow tensor, required for testing
          Representations for items involved in the interactions. Shape: **[number of interactions, dimensionality of \
          item representations]**.
      item_bias: Tensorflow tensor, required for testing
          Biases for items involved in the interactions. Shape: **[number of interactions, 1]**.
      p_item: Tensorflow tensor, required for training
          Representations for positive items involved in the interactions. Shape: **[number of interactions, dimensionality of \
          item representations]**.
      p_item_bias: Tensorflow tensor, required for training
          Biases for positive items involved in the interactions. Shape: **[number of interactions, 1]**.
      n_item: Tensorflow tensor, required for training
          Representations for negative items involved in the interactions. Shape: **[number of interactions, dimensionality of \
          item representations]**.
      n_item_bias: Tensorflow tensor, required for training
          Biases for negative items involved in the interactions. Shape: **[number of interactions, 1]**.
      weights: Tensorflow tensor, optional
          Weights :math:`w`. Shape: **[number of interactions, 1]**.
      margin: float, optional
          Margin :math:`m`. Default to 1.0.
      train: bool, optionl
          An indicator for training or serving phase.
      scope: str, optional
          Scope for module variables.
      reuse: bool, optional
          Whether or not to reuse module variables.
      
      References
      ----------
      .. [cml] Hsieh, C.K., Yang, L., Cui, Y., Lin, T.Y., Belongie, S. and Estrin, D., 2017, April. Collaborative metric learning. \
          In Proceedings of the 26th International Conference on World Wide Web (pp. 193-201). International World Wide Web Conferences \
          Steering Committee.
      """
  
      def __init__(self, user, item=None, item_bias=None, p_item=None,
      p_item_bias=None,  n_item=None, n_item_bias=None, weights=1.0, margin=1.0, train=None, 
      scope=None, reuse=False):
  
          self._weights = weights
          self._margin = margin
  
          super(PairwiseEuDist, self).__init__(user=user, item=item, item_bias=item_bias, p_item=p_item,
          n_item=n_item, p_item_bias=p_item_bias, n_item_bias=n_item_bias, train=train, scope=scope, reuse=reuse)
  
      def _build_training_graph(self):
          
          with tf.variable_scope(self._scope, reuse=self._reuse):
  
              l2_user_pos = tf.reduce_sum(tf.square(tf.subtract(self._user, self._p_item)),
                                          reduction_indices=1,
                                          keep_dims=True, name="l2_user_pos")
              l2_user_neg = tf.reduce_sum(tf.square(tf.subtract(self._user, self._n_item)),
                                          reduction_indices=1,
                                          keep_dims=True, name="l2_user_neg")
              pos_score = (-l2_user_pos) + self._p_item_bias
              neg_score = (-l2_user_neg) + self._n_item_bias
              diff = pos_score - neg_score
              self._loss = tf.reduce_sum(self._weights * tf.maximum(self._margin - diff, 0))
  
      def _build_serving_graph(self):
          
          with tf.variable_scope(self._scope, reuse=self._reuse):
              item_norms = tf.reduce_sum(tf.square(self._item), axis=1)
              self._outputs.append(2 * tf.matmul(self._user, self._item, transpose_b=True) + \
                              tf.reshape(self._item_bias, [-1]) - tf.reshape(item_norms, [-1]))
  