import tensorflow as tf



def dense_maxnorm(var_matrix, maxnorm=1.0):
    '''Similar to dense_maxnorm_update(), except this returns a new Tensor
       instead of an operation that modifies var_matrix.

    Args:
        var_matrix: 2D tensor (Variable)
        maxnorm: the maximum Euclidean norm

    Returns:
        A new tensor where all rows have been scaled as necessary
    '''
    axis_norms = tf.sqrt(tf.reduce_sum(tf.square(var_matrix), 1))
    scaling = maxnorm / tf.maximum(axis_norms, maxnorm)
    return var_matrix * tf.expand_dims(scaling, 1)


class BaseModel(object):
    ''' Base class for embedding-based relational learning models that use 
        maxnorm regularization. Subclasses must implement _create_model() and
        populate self.train_step, and can optionally populate self.post_step for 
        post-processing.
    
    Note: When model_type is 'ranking_margin', the mini-batch provider returned
    by _create_batch_provider() must provide instances in alternating 
    pos/neg pairs: [pos, neg, pos, neg, ...]. This is satisfied when using 
    ContrastiveTrainingProvider; be careful if you use a different one.
    
    Args:
