     dimBatch = srcWordBatch.size();
   }
 
-  auto buildEncoderGRU = [=](const std::string& prefix){
+  auto encoderGRU = [=](const std::string& prefix) {
     auto U = g->param(prefix + "_U", {dimEncState, 2 * dimEncState},
                       init=glorot_uniform);
 

    g->clear();

    // fake batch
    auto batch = generateBatch(batchSize);
    construct(g, batch);

    g->forward();
    g->graphviz("nematus.dot");

    return RNN<GRUFast>(encParams);
  };

  auto encState0 = name(g->zeros(shape={dimBatch, dimEncState}), "start");

  auto statesFw = encoderGRU("encoder").apply(inputs.begin(),
                                              inputs.end(),
                                              encState0);

  auto statesBw = encoderGRU("encoder_r").apply(inputs.rbegin(),
                                                inputs.rend(),
                                                encState0);

  std::vector<Expr> biStates;
  auto itFw = statesFw.begin();
  auto itBw = statesBw.rbegin();
  while(itFw != statesFw.end())
    biStates.push_back(concatenate({*itFw++, *itBw++}, axis=1));

  // add proper axes and make this a 3D tensor
  auto encContext = concatenate(biStates, axis=2);
  auto meanContext = mean(encContext, axis=2);

  /*** decoder layer 1 ****************************************************/

  auto Wi = g->param("ff_state_W", {2 * dimEncState, dimDecState}, init=glorot_uniform);
  auto bi = g->param("ff_state_b", {1, dimDecState}, init=zeros);

  auto decState0 = debug(tanh(dot(meanContext, Wi) + bi), "decState0");

  auto Wemb_dec = g->param("Wemb_dec", {dimTrgVoc, dimTrgEmb}, init=glorot_uniform);

  std::vector<Expr> outputs;
  auto emptyEmbedding = name(g->zeros(shape={dimBatch, dimTrgEmb}), "emptyEmbedding");
  outputs.push_back(emptyEmbedding);

  i = 0;
  for(auto& trgWordBatch : srcSentenceBatch) {
    auto y = name(rows(Wemb_dec, trgWordBatch), "y_" + std::to_string(i++));
    outputs.push_back(y);
  }

  auto decoderGRULayer1 = [=]() {
    auto U = g->param("decoder_U", {dimDecState, 2 * dimDecState},
                      init=glorot_uniform);

    auto W = g->param("decoder_W", {dimTrgEmb, 2 * dimDecState},
                      init=glorot_uniform);

    auto b = g->param("decoder_b", {1, 2 * dimDecState}, init=zeros);

    auto Ux = g->param("decoder_Ux", {dimDecState, dimDecState},
                      init=glorot_uniform);

    auto Wx = g->param("decoder_Wx", {dimTrgEmb, dimDecState},
                       init=glorot_uniform);

    auto bx = g->param("decoder_bx", {1, dimDecState}, init=zeros);

    ParametersGRUFast encParams;
    encParams.U = concatenate({U, Ux}, axis=1);
    encParams.W = concatenate({W, Wx}, axis=1);
    encParams.b = concatenate({b, bx}, axis=1);

    return RNN<GRUFast>(encParams);
  };

  auto statesLayer1 = decoderGRULayer1().apply(outputs.begin(),
                                               outputs.end(),
                                               decState0);

  i = 0;
  for(auto s : statesLayer1)
    debug(s, "decoder state layer1 : " + std::to_string(i++));

  /*** decoder layer 2 ****************************************************/

}

SentBatch generateSrcBatch(size_t batchSize) {
  //size_t length = rand() % 40 + 10;
  //return SentBatch(length, WordBatch(batchSize));

  // das ist ein Test . </s>
  return SentBatch({
    WordBatch(batchSize, 13),
    WordBatch(batchSize, 15),
    WordBatch(batchSize, 20),
    WordBatch(batchSize, 2548),
    WordBatch(batchSize, 4),
    WordBatch(batchSize, 0)
  });
}

SentBatch generateTrgBatch(size_t batchSize) {
  //size_t length = rand() % 40 + 10;
  //return SentBatch(length, WordBatch(batchSize));

  // this is a test . </s>
  return SentBatch({
    WordBatch(batchSize, 21),
    WordBatch(batchSize, 11),
    WordBatch(batchSize, 10),
    WordBatch(batchSize, 1078),
    WordBatch(batchSize, 5),
    WordBatch(batchSize, 0)
  });
}

int main(int argc, char** argv) {
  cudaSetDevice(0);

