//  [python]
def dynamic_head(configs,
                 proposal_box,
                 v_mask,
                 q_mask,
                 vfeats0,
                 qfeats0,
                 drop_rate,
                 dx,
                 dy,
                 boxes,
                 y1,
                 y2,
                 train,
                 reuse=None,
                 name='dynamic_head'):
    with tf.variable_scope(name, reuse=tf.AUTO_REUSE):

        batch_size = tf.shape(vfeats0)[0]
        dim = tf.shape(vfeats0)[-1]

        box_index = tf.reshape(tf.tile(tf.expand_dims(tf.range(batch_size), -1), [1, 100]), [batch_size * 100])
        inputs = tf.image.crop_and_resize(tf.expand_dims(vfeats0, 1),
                                          tf.tile(boxes, [batch_size, 1]),
                                          box_ind=box_index,
                                          crop_size=(1, 16))
        inputs = tf.reshape(inputs, [batch_size, 100, 1, 16, dim])

        # outputs = tf.expand_dims(vfeats0, 1)
        length = tf.reduce_sum(v_mask, -1)
        ll = tf.cast(length, tf.float32)
        N = batch_size
        b = 100
        l = 16
        d = 256

        features = tf.reshape(inputs, [N * b, l, d])
        pro_features = tf.get_variable(
            "pro_features", [b, d],
            dtype=tf.float32,
            initializer=tf.random_normal_initializer(),
            trainable=True)
        pro_features = tf.expand_dims(pro_features, 0)
        # MHSA
        pro_features2 = multihead_attention_block(
            pro_features,
            dim=d,
            num_heads=4,
            mask=None,
            use_bias=True,
            drop_rate=drop_rate,
            reuse=False,
            name='multihead_attention_pro')
        pro_features = pro_features + tf.nn.dropout(pro_features2,
                                                    rate=drop_rate)
        pro_features = layer_norm(pro_features,
                                  name="layer_norm3")  #[1, b, 128]
        pro_features_batch = tf.reshape(tf.tile(pro_features, [N, 1, 1]),
                                        [1, N * b, d])

        parameters = tf.layers.dense(pro_features_batch,
                                     2 * d * 64,
                                     name="dynamic_layer")
        parameters = tf.reshape(parameters, [N * b, 1, 2 * d * 64])
        param1 = tf.reshape(parameters[:, :, :d * 64], [-1, d, 64])
        param2 = tf.reshape(parameters[:, :, d * 64:], [-1, 64, d])

        features = tf.matmul(features, param1)  #[Nb, 1, 32]
        features = layer_norm(features, name="layer_norm4")
        features = tf.nn.relu(features)

        features = tf.matmul(features, param2)  #[Nb, 1, 128]
        features = layer_norm(features, name="layer_norm5")
        features = tf.nn.relu(features)

        # not pro feature for 4 lines
        features = tf.reshape(features, [N * b, d * l])
        features = tf.layers.dense(features, d, name="out_layer")
        features = layer_norm(features, name="layer_norm6")
        features = tf.nn.relu(features)

        features = tf.reshape(features, [N, b, d])

        features = pro_features + tf.nn.dropout(features,
                                                rate=drop_rate)  #[1, b, 128]
        features = layer_norm(features, name="layer_norm7")

        inputs = tf.reshape(features, [N, b, d])

        position_embedding = tf.layers.dense(proposal_box, 32, activation=tf.nn.relu) #[k,256]

        # weighted pooling and concatenation
        inputs = context_query_position_concat(inputs,
                                               qfeats0,
                                               position_embedding,
                                               q_mask=q_mask,
                                               reuse=False,
                                               name='context_query_position_concat')

        x_index = tf.cast(tf.reshape(tf.arg_max(y1, 1), [-1, 1]), tf.float32)
        y_index = tf.cast(tf.reshape(tf.arg_max(y2, 1), [-1, 1]), tf.float32)

        length = tf.reduce_sum(v_mask, -1)
        ll = tf.cast(length, tf.float32)
        x = tf.cast(x_index, tf.float32) # [8, 1]
        y = tf.cast(y_index, tf.float32)

        dx = tf.expand_dims((proposal_box[:, 0] - proposal_box[:, 1]), 0) * tf.expand_dims(ll, -1) # [1,100]*[8,1]
        dy = tf.expand_dims((proposal_box[:, 0] + proposal_box[:, 1]), 0) * tf.expand_dims(ll, -1)

        l1 = (tf.abs(dx-x) + tf.abs(dy-y))/tf.expand_dims(ll, 1)

        union = (tf.minimum(dx, x), tf.maximum(dy, y))

        inter = (tf.maximum(dx, x), tf.minimum(dy, y))

        iou = tf.maximum(
            tf.cast((inter[1] - inter[0]), tf.float32) / tf.cast(
                (union[1] - union[0]), tf.float32), 0.0)

        zero = tf.zeros_like(iou)

        iou = tf.where(dy - dx > 0, x=iou, y=zero)

        match_cost = 1-iou + l1 #[8, 100]
        assigned_label = tf.arg_min(match_cost, -1) # [8]

        one = tf.ones_like(iou)

        output = tf.layers.dense(inputs, 256, kernel_regularizer=tf.contrib.layers.l2_regularizer(0.001))
        output = layer_norm(output, name="layer_norm8")
        output = tf.nn.relu(output)
        output = tf.nn.dropout(output, rate=drop_rate)
        logits = tf.squeeze(
            tf.layers.dense(output, 1, activation=tf.nn.sigmoid), -1) #[bs, 100]
        # logits = tf.squeeze(
        #     tf.layers.dense(output, 1), -1)
        # reg_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=iou, logits=logits))
        weights = tf.where(iou < 0.001, x=0.92 + zero, y=one)
        reg_loss = tf.losses.mean_squared_error(labels=iou, predictions=logits, weights=weights)

        p_s = tf.cond(train, lambda: tf.batch_gather(proposal_box[:, 0], tf.arg_max(iou, -1)), lambda: tf.batch_gather(proposal_box[:, 0], tf.arg_max(logits, -1)))
        p_e = tf.cond(train, lambda: tf.batch_gather(proposal_box[:, 1], tf.arg_max(iou, -1)), lambda: tf.batch_gather(proposal_box[:, 1], tf.arg_max(logits, -1)))

        p_x = tf.reshape((p_s - p_e) * ll, [-1, 1]) #(32,)
        p_y = tf.reshape((p_s + p_e) * ll, [-1, 1])
        u = (tf.minimum(p_x, x), tf.maximum(p_y, y))
        i = (tf.maximum(p_x, x), tf.minimum(p_y, y))
        iou_pred = tf.maximum(
            tf.cast((i[1] - i[0]), tf.float32) / tf.cast(
                (u[1] - u[0]), tf.float32), 1e-10)
        c = tf.cast((u[1] - u[0]), tf.float32)
        # I = tf.maximum(tf.cast((i[1] - i[0]), tf.float32), 0.0)
        # U = tf.cast(p_y - p_x + y - x, tf.float32)
        # dcenter = 0.25 * tf.cast(p_y + p_x - y - x, tf.float32) **2
        # # giou = iou_pred - (c - U + I) / c
        # diou = iou_pred - dcenter/c **2 
        one = tf.ones_like(iou_pred)
        sig = tf.where(iou_pred > 0.95, x=one, y=iou_pred)
       
        iou_loss = tf.reduce_mean(tf.ones_like(iou_pred) - sig)
        # iou_loss = tf.reduce_mean(tf.ones_like(iou_pred) - giou)
        # iou_loss = tf.reduce_mean(tf.ones_like(iou_pred) - diou)
        
        
        p_s_label = tf.cast((x + y) / (2 * ll), tf.float32)
        p_e_label = tf.cast((y - x) / (2 * ll), tf.float32)
        norm = tf.cast((y - x + 1) / ll, tf.float32)

        # l1_loss = tf.reduce_mean(
        #     tf.abs(p_s - p_s_label) / norm + tf.abs(p_e - p_e_label) / norm)
        # l1_loss = tf.reduce_mean(
        #     tf.abs(p_s - p_s_label) + tf.abs(p_e - p_e_label))
        l1_loss = tf.reduce_mean((tf.abs(p_x - x)+tf.abs(p_y - y))/tf.expand_dims(ll, 1))
        # l1_loss = 0
        regular = tf.reduce_mean(
            tf.nn.relu(proposal_box[:, 1] - proposal_box[:, 0]) +
            tf.nn.relu(proposal_box[:, 1] + proposal_box[:, 0] - 1.0))

        regular2 = 0.0

        proposal_box1 = 0
        l1reg_loss = 0

        p_x = tf.cast(tf.rint(p_x), tf.int32)
        p_y = tf.cast(tf.rint(p_y), tf.int32)

        return reg_loss, l1reg_loss, l1_loss, iou_loss, regular, regular2, iou, [dx, dy], p_x, p_y