/**
   * Returns a copy of this neural net
   *
   * @return INeuralNet Copy of this neural net
   */
  public INeuralNet copy() {

    // Resulting neural net
    AbstractNeuralNet result = null;

    try {
      result = this.getClass().newInstance();

      // Copy the input layer
      result.inputLayer = this.inputLayer.copy();

      // Copy hidden layers
      ILayer<? extends INeuron> lastCopiedLayer = result.inputLayer;
      for (LinkedLayer hl : this.hiddenLayers) {
        // Copy hidden layer
        LinkedLayer hlr = hl.copy(lastCopiedLayer);
        result.addHlayer(hlr);

        // Update last copied layer
        lastCopiedLayer = hlr;
      }

      // Copy the output layer
      result.outputLayer = this.outputLayer.copy(lastCopiedLayer);
    } catch (InstantiationException e) {
      System.out.println("Instantiation Error " + e.getLocalizedMessage());
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      System.out.println("Illegal Access Error " + e.getLocalizedMessage());
      e.printStackTrace();
    }
    return result;
  }
 public AbstractNeuralNet parse(XmlElement xml) {
   // Resulting object
   AbstractNeuralNet result = (AbstractNeuralNet) xml.object();
   // Unmarshal input layer
   result.inputLayer = xml.<InputLayer>get("input-layer");
   // Unmarshal hidden layers
   result.hiddenLayers = xml.<ArrayList<LinkedLayer>>get("hidden-layers");
   // Update neuron references
   ILayer<? extends INeuron> previousLayer = result.inputLayer;
   for (LinkedLayer hiddenLayer : result.hiddenLayers) {
     for (int i = 0; i < hiddenLayer.getNofneurons(); i++) {
       Link[] links = hiddenLayer.getNeuron(i).getLinks();
       for (int j = 0; j < links.length; j++) {
         links[j].setTarget(hiddenLayer.getNeuron(i));
         if (!links[j].isBroken() && j < previousLayer.getMaxnofneurons())
           links[j].setOrigin(previousLayer.getNeuron(j));
         else links[j].setOrigin(null);
       }
     }
     previousLayer = hiddenLayer;
   }
   // Unmarshal output layer
   result.outputLayer = xml.<LinkedLayer>get("output-layer");
   // Update neuron references
   for (int i = 0; i < result.outputLayer.getNofneurons(); i++) {
     Link[] links = ((LinkedNeuron) result.outputLayer.getNeuron(i)).getLinks();
     for (int j = 0; j < links.length; j++) {
       links[j].setTarget(result.outputLayer.getNeuron(i));
       if (!links[j].isBroken() && j < previousLayer.getMaxnofneurons())
         links[j].setOrigin(previousLayer.getNeuron(j));
       else links[j].setOrigin(null);
     }
   }
   // Return result
   return result;
 }