public static void main(String[] args) throws IOException {
    if (args.length == 3) {
      
      // read the training and evaluation databases
      Vector<Map<Integer,Double>> training = Train.readDB(new File(args[0]));
      Vector<Map<Integer,Double>> evaluation = Train.readDB(new File(args[2]));
      
      // read model (in for of baseUserID -> topk(userID, sim))
      Vector<HashMap<Integer,Double>> model = Predict.readModel(new File(args[1]));
      
      
      // compute user average ratings
      double[] avgs = new double[training.size()];
      for (int i = 0; i < training.size(); i ++) {
        avgs[i] = 0.0;
        for (int iid : training.get(i).keySet()) {
          avgs[i] += training.get(i).get(iid);
        }
        avgs[i] = (training.get(i).size() > 0) ? avgs[i] / ((double)training.get(i).size()) : 0.0;
      }
      
      // perform evaluation
      for (int uid = 0; uid < evaluation.size(); uid ++) {
        // get model of uid
        Map<Integer,Double> modelOfUid = model.get(uid);
        double avgOfUid = avgs[uid];
        
        for (int iid : evaluation.get(uid).keySet()) {
          double expectedRate = evaluation.get(uid).get(iid);
          
          double predictedRate = 0.0;
          double sumOfSimilarities = 0.0;
          
          // compute prediction
          for (int neighborId : modelOfUid.keySet()) {
            Map<Integer,Double> neighborRates = training.get(neighborId);
            Double neighborRateD = neighborRates.get(iid);
            if (neighborRateD != null) {
              double neighborSim = modelOfUid.get(neighborId);
              double neighborRate = neighborRateD.doubleValue();
              double avgOfNeighbor = avgs[neighborId];
              
              // coffee method
              predictedRate += neighborSim * (neighborRate - avgOfNeighbor);
              sumOfSimilarities += Math.abs(neighborSim);
            }
          }
          
          // predicted rate is computed
          predictedRate = (Math.abs(sumOfSimilarities) < 10.0E-8) ? 0.0 : predictedRate / sumOfSimilarities;
          predictedRate += avgOfUid;
          
          System.out.println(uid + "\t" + iid + "\t" + predictedRate + "\t" + expectedRate);
        }
      }
    } else {
      System.err.println("Usage: " + Predict.class.getCanonicalName() + " training model evaluation");
    }
  }