     g->clear();
 
     // fake batch
-    auto batch = generateBatch(batchSize);
-    construct(g, batch);
+    auto srcBatch = generateSrcBatch(batchSize);
+    auto trgBatch = generateTrgBatch(batchSize);
+    construct(g, srcBatch, trgBatch);
 
     g->forward();
     g->graphviz("nematus.dot");

    return RNN<GRUFast>(encParams);
  };

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

  auto encForward = buildEncoderGRU("encoder");
  auto statesForward = encForward.apply(inputs.begin(), inputs.end(),
                                        encStartState);

  auto encBackward = buildEncoderGRU("encoder_r");
  auto statesBackward = encBackward.apply(inputs.rbegin(), inputs.rend(),
                                          encStartState);

  std::vector<Expr> joinedStates;
  auto itFw = statesForward.begin();
  auto itBw = statesBackward.rbegin();
  while(itFw != statesForward.end()) {
    // add proper axes
    joinedStates.push_back(concatenate({*itFw++, *itBw++}, axis=1));
  }

  // add proper axes and make this a 3D tensor
  auto encContext = debug(concatenate(joinedStates, axis=2), "context");
  auto decStartState = debug(mean(encContext, axis=2), "decoderStart");

}

SentBatch generateBatch(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, 8306),
    WordBatch(batchSize, 4),
    WordBatch(batchSize, 0)
  });
}

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


typedef std::vector<WordBatch> SentBatch;

void load(ExpressionGraphPtr g, const std::string& name) {
  auto numpy = cnpy::npz_load(name);

  auto parameters = {
    // Source word embeddings
    "Wemb",

    // GRU in encoder
    "encoder_U", "encoder_W", "encoder_b",
    "encoder_Ux", "encoder_Wx", "encoder_bx",

    // GRU in encoder, reversed
    "encoder_r_U", "encoder_r_W", "encoder_r_b",
    "encoder_r_Ux", "encoder_r_Wx", "encoder_r_bx",

    // Transformation of decoder input state
    "ff_state_W", "ff_state_b",

    // Target word embeddings
    "Wemb_dec",

    // GRU layer 1 in decoder
    "decoder_U", "decoder_W", "decoder_b",
    "decoder_Ux", "decoder_Wx", "decoder_bx"
  };

  for(auto name : parameters) {
    Shape shape;
    if(numpy[name].shape.size() == 2) {
      shape[0] = numpy[name].shape[0];
      shape[1] = numpy[name].shape[1];
    }
    else if(numpy[name].shape.size() == 1) {
      shape[0] = 1;
      shape[1] = numpy[name].shape[0];
    }

    g->param(name, shape, init=from_numpy(numpy[name]));
  }
}

void construct(ExpressionGraphPtr g,
               const SentBatch& srcSentenceBatch,
               const SentBatch& trgSentenceBatch) {
  g->clear();

  int dimSrcVoc = g->get("Wemb") ? g->get("Wemb")->shape()[0] : 85000;
  int dimSrcEmb = g->get("Wemb") ? g->get("Wemb")->shape()[1] : 500;
  int dimEncState = g->get("encoder_U") ? g->get("encoder_U")->shape()[0] : 1024;

  int dimTrgVoc = g->get("Wemb_dec") ? g->get("Wemb_dec")->shape()[0] : 85000;
  int dimTrgEmb = g->get("Wemb_dec") ? g->get("Wemb_dec")->shape()[1] : 500;
  int dimDecState = g->get("decoder_U") ? g->get("decoder_U")->shape()[0] : 1024;

  int dimBatch = 1;

  /****************************** encoder *********************************/

  auto Wemb = g->param("Wemb", {dimSrcVoc, dimSrcEmb}, init=glorot_uniform);

