//  [python]
def __init__(self, input_x1, input_x2, word_embedding_type, vocab_size, embedding_size,
                 encoder_type, cnn_encoder, rnn_encoder, dense_layer, weight_sharing):
        """
        Args:
            cnn_encoder: instance of CNNEncoder
            rnn_encoder: instance of RNNEncoder
        """
        # input word level dropout, data augmentation, invariance to small input change
        # self.shape = tf.shape(self.input_x1)
        # self.mask1 = tf.cast(tf.random_uniform(self.shape) > 0.1, tf.int32)
        # self.mask2 = tf.cast(tf.random_uniform(self.shape) > 0.1, tf.int32)
        # self.input_x1 = self.input_x1 * self.mask1
        # self.input_x2 = self.input_x2 * self.mask2
        self._encoder_type = encoder_type
        self._rnn_encoder = rnn_encoder
        seqlen1 = tf.cast(tf.reduce_sum(tf.sign(input_x1), 1), tf.int32)
        seqlen2 = tf.cast(tf.reduce_sum(tf.sign(input_x2), 1), tf.int32)
        assert word_embedding_type in {'rand', 'static', 'non-static'}, 'Invalid word embedding type'
        with tf.variable_scope("embedding"):
            if word_embedding_type == "rand":
                self.W = tf.Variable(
                    tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
                    trainable=True, name="W")  # tf.truncated_normal()
            else:
                trainable = False if word_embedding_type == "static" else True
                self.W = tf.Variable(
                    tf.constant(0.0, shape=[vocab_size, embedding_size]),
                    trainable=trainable, name="W")
                # embedding_placeholder = tf.placeholder(tf.float32, [vocab_size, embedding_size])
                # self.embedding_init = self.W.assign(embedding_placeholder)
            self.embedded_1 = tf.nn.embedding_lookup(self.W, input_x1)
            self.embedded_2 = tf.nn.embedding_lookup(self.W, input_x2)
            # Input embedding dropout. very sensitive to the dropout rate !
            self.embedded_1 = tf.nn.dropout(self.embedded_1, 0.7)
            self.embedded_2 = tf.nn.dropout(self.embedded_2, 0.7)
        if weight_sharing:
            cnn_scope1, cnn_scope2, rnn_scope1, rnn_scope2 = "CNN", "CNN", "RNN", "RNN"
        else:
            cnn_scope1, cnn_scope2, rnn_scope1, rnn_scope2 = "CNN1", "CNN2", "RNN1", "RNN2"
        if encoder_type.lower() == 'cnn':
            self.out1 = cnn_encoder.forward(self.embedded_1, cnn_scope1)
            self.out2 = cnn_encoder.forward(self.embedded_2, cnn_scope2)
        elif encoder_type.lower() == 'rnn':
            self.out1 = rnn_encoder.forward(self.embedded_1, seqlen1, rnn_scope1)
            self.out2 = rnn_encoder.forward(self.embedded_2, seqlen2, rnn_scope2)
        elif encoder_type.lower() == 'rcnn':
            cnn_out1 = cnn_encoder.forward(self.embedded_1, cnn_scope1)
            cnn_out2 = cnn_encoder.forward(self.embedded_2, cnn_scope2)
            rnn_out1 = rnn_encoder.forward(self.embedded_1, seqlen1, rnn_scope1)
            rnn_out2 = rnn_encoder.forward(self.embedded_2, seqlen2, rnn_scope2)
            self.out1 = tf.concat([cnn_out1, rnn_out1], axis=1)
            self.out2 = tf.concat([cnn_out2, rnn_out2], axis=1)
        else:
            raise ValueError("Invalid encoder type.")

        if dense_layer:
            with tf.variable_scope("fc"):
                out_dim = self.out1.get_shape().as_list()[1]
                W1 = tf.get_variable("W1", shape=[out_dim, 128], initializer=tf.contrib.layers.xavier_initializer())
                b1 = tf.Variable(tf.constant(0.1, shape=[128]), name="b1")
                W2 = tf.get_variable("W2", shape=[out_dim, 128], initializer=tf.contrib.layers.xavier_initializer())
                b2 = tf.Variable(tf.constant(0.1, shape=[128]), name="b2")
                self.out1 = tf.nn.xw_plus_b(self.out1, W1, b1, name="out1")
                self.out2 = tf.nn.xw_plus_b(self.out2, W2, b2, name="out2")