public void saveConfig() {
    File file = null;
    try {
      String home = System.getProperty("user.home");
      file = new File(home, EncogWorkBench.CONFIG_FILENAME);

      OutputStream os = new FileOutputStream(file);
      EncogWriteHelper out = new EncogWriteHelper(os);
      out.addSection("ENCOG");
      out.addSubSection("TRAINING");

      out.writeProperty(EncogWorkBenchConfig.PROPERTY_DEFAULT_ERROR, this.defaultError);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_THREAD_COUNT, this.threadCount);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_USE_GPU, this.useOpenCL);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_ERROR_CALC, this.errorCalculation);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_STEP_COUNT, this.iterationStepCount);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_TRAINING_HISTORY, this.trainingHistory);
      out.writeProperty(
          EncogWorkBenchConfig.PROPERTY_TRAINING_IMPROVEMENT, this.showTrainingImprovement);
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_LOG_LEVEL, getLogLevel());

      out.addSubSection("PATHS");
      out.writeProperty(EncogWorkBenchConfig.PROPERTY_PROJECT_ROOT, this.projectRoot);

      out.flush();
      os.close();
    } catch (IOException ex) {
      if (file != null) EncogWorkBench.displayError("Can't write config file", file.toString());
    }
  }
 /** {@inheritDoc} */
 @Override
 public final void save(final OutputStream os, final Object obj) {
   final EncogWriteHelper out = new EncogWriteHelper(os);
   final SOM som = (SOM) obj;
   out.addSection("SOM");
   out.addSubSection("PARAMS");
   out.addProperties(som.getProperties());
   out.addSubSection("NETWORK");
   out.writeProperty(PersistConst.WEIGHTS, som.getWeights());
   out.writeProperty(PersistConst.INPUT_COUNT, som.getInputCount());
   out.writeProperty(PersistConst.OUTPUT_COUNT, som.getOutputNeuronCount());
   out.flush();
 }
  /** {@inheritDoc} */
  @Override
  public final void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final BAM bam = (BAM) obj;
    out.addSection("BAM");
    out.addSubSection("PARAMS");
    out.addProperties(bam.getProperties());
    out.addSubSection("NETWORK");

    out.writeProperty(PersistConst.PROPERTY_F1_COUNT, bam.getF1Count());
    out.writeProperty(PersistConst.PROPERTY_F2_COUNT, bam.getF2Count());
    out.writeProperty(PersistConst.PROPERTY_WEIGHTS_F1_F2, bam.getWeightsF1toF2());
    out.writeProperty(PersistConst.PROPERTY_WEIGHTS_F2_F1, bam.getWeightsF2toF1());

    out.flush();
  }
  @Override
  public void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final NEATPopulation pop = (NEATPopulation) obj;
    out.addSection("NEAT-POPULATION");
    out.addSubSection("CONFIG");
    out.writeProperty(PersistConst.ACTIVATION_CYCLES, pop.getActivationCycles());

    if (pop.isHyperNEAT()) {
      out.writeProperty(NEATPopulation.PROPERTY_NEAT_ACTIVATION, PersistNEATPopulation.TYPE_CPPN);
    } else {
      final ActivationFunction af = pop.getActivationFunctions().getList().get(0).getObj();
      out.writeProperty(NEATPopulation.PROPERTY_NEAT_ACTIVATION, af);
    }

    out.writeProperty(PersistConst.INPUT_COUNT, pop.getInputCount());
    out.writeProperty(PersistConst.OUTPUT_COUNT, pop.getOutputCount());
    out.writeProperty(NEATPopulation.PROPERTY_CYCLES, pop.getActivationCycles());
    out.writeProperty(NEATPopulation.PROPERTY_POPULATION_SIZE, pop.getPopulationSize());
    out.writeProperty(NEATPopulation.PROPERTY_SURVIVAL_RATE, pop.getSurvivalRate());
    out.addSubSection("INNOVATIONS");
    if (pop.getInnovations() != null) {
      for (final String key : pop.getInnovations().getInnovations().keySet()) {
        final NEATInnovation innovation = pop.getInnovations().getInnovations().get(key);
        out.addColumn(key);
        out.addColumn(innovation.getInnovationID());
        out.addColumn(innovation.getNeuronID());
        out.writeLine();
      }
    }

    out.addSubSection("SPECIES");

    // make sure the best species goes first
    final Species bestSpecies = pop.determineBestSpecies();
    if (bestSpecies != null) {
      saveSpecies(out, bestSpecies);
    }

    // now write the other species, other than the best one
    for (final Species species : pop.getSpecies()) {
      if (species != bestSpecies) {
        saveSpecies(out, species);
      }
    }
    out.flush();
  }
  /**
   * Save the data fields.
   *
   * @param out The output file.
   */
  private void saveData(final EncogWriteHelper out) {
    saveSubSection(out, "DATA", "CONFIG");
    out.addSubSection("STATS");
    out.addColumn("name");
    out.addColumn("isclass");
    out.addColumn("iscomplete");
    out.addColumn("isint");
    out.addColumn("isreal");
    out.addColumn("amax");
    out.addColumn("amin");
    out.addColumn("mean");
    out.addColumn("sdev");
    out.writeLine();

    for (final DataField field : this.script.getFields()) {
      out.addColumn(field.getName());
      out.addColumn(field.isClass());
      out.addColumn(field.isComplete());
      out.addColumn(field.isInteger());
      out.addColumn(field.isReal());
      out.addColumn(field.getMax());
      out.addColumn(field.getMin());
      out.addColumn(field.getMean());
      out.addColumn(field.getStandardDeviation());
      out.writeLine();
    }
    out.flush();

    out.addSubSection("CLASSES");
    out.addColumn("field");
    out.addColumn("code");
    out.addColumn("name");
    out.writeLine();

    for (final DataField field : this.script.getFields()) {
      if (field.isClass()) {
        for (final AnalystClassItem col : field.getClassMembers()) {
          out.addColumn(field.getName());
          out.addColumn(col.getCode());
          out.addColumn(col.getName());
          out.addColumn(col.getCount());
          out.writeLine();
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final RBFNetwork net = (RBFNetwork) obj;
    final FlatNetworkRBF flat = (FlatNetworkRBF) net.getFlat();
    out.addSection("RBF-NETWORK");
    out.addSubSection("PARAMS");
    out.addProperties(net.getProperties());
    out.addSubSection("NETWORK");
    out.writeProperty(BasicNetwork.TAG_BEGIN_TRAINING, flat.getBeginTraining());
    out.writeProperty(BasicNetwork.TAG_CONNECTION_LIMIT, flat.getConnectionLimit());
    out.writeProperty(BasicNetwork.TAG_CONTEXT_TARGET_OFFSET, flat.getContextTargetOffset());
    out.writeProperty(BasicNetwork.TAG_CONTEXT_TARGET_SIZE, flat.getContextTargetSize());
    out.writeProperty(BasicNetwork.TAG_END_TRAINING, flat.getEndTraining());
    out.writeProperty(BasicNetwork.TAG_HAS_CONTEXT, flat.getHasContext());
    out.writeProperty(PersistConst.INPUT_COUNT, flat.getInputCount());
    out.writeProperty(BasicNetwork.TAG_LAYER_COUNTS, flat.getLayerCounts());
    out.writeProperty(BasicNetwork.TAG_LAYER_FEED_COUNTS, flat.getLayerFeedCounts());
    out.writeProperty(BasicNetwork.TAG_LAYER_CONTEXT_COUNT, flat.getLayerContextCount());
    out.writeProperty(BasicNetwork.TAG_LAYER_INDEX, flat.getLayerIndex());
    out.writeProperty(PersistConst.OUTPUT, flat.getLayerOutput());
    out.writeProperty(PersistConst.OUTPUT_COUNT, flat.getOutputCount());
    out.writeProperty(BasicNetwork.TAG_WEIGHT_INDEX, flat.getWeightIndex());
    out.writeProperty(PersistConst.WEIGHTS, flat.getWeights());
    out.writeProperty(BasicNetwork.TAG_BIAS_ACTIVATION, flat.getBiasActivation());
    out.addSubSection("ACTIVATION");
    for (final ActivationFunction af : flat.getActivationFunctions()) {
      out.addColumn(af.getClass().getSimpleName());
      for (int i = 0; i < af.getParams().length; i++) {
        out.addColumn(af.getParams()[i]);
      }
      out.writeLine();
    }
    out.addSubSection("RBF");
    for (final RadialBasisFunction rbf : flat.getRBF()) {
      out.addColumn(rbf.getClass().getSimpleName());
      out.addColumn(rbf.getWidth());
      out.addColumn(rbf.getPeak());
      for (int i = 0; i < rbf.getCenters().length; i++) {
        out.addColumn(rbf.getCenters()[i]);
      }
      out.writeLine();
    }

    out.flush();
  }
  /** {@inheritDoc} */
  @Override
  public final void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final CPN cpn = (CPN) obj;
    out.addSection("CPN");
    out.addSubSection("PARAMS");
    out.addProperties(cpn.getProperties());
    out.addSubSection("NETWORK");

    out.writeProperty(PersistConst.INPUT_COUNT, cpn.getInputCount());
    out.writeProperty(PersistConst.INSTAR, cpn.getInstarCount());
    out.writeProperty(PersistConst.OUTPUT_COUNT, cpn.getOutputCount());
    out.writeProperty(PersistCPN.PROPERTY_inputToInstar, cpn.getWeightsInputToInstar());
    out.writeProperty(PersistCPN.PROPERTY_instarToInput, cpn.getWeightsInstarToOutstar());
    out.writeProperty(PersistCPN.PROPERTY_winnerCount, cpn.getWinnerCount());

    out.flush();
  }
  /** {@inheritDoc} */
  @Override
  public void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final BasicNetwork net = (BasicNetwork) obj;
    final FlatNetwork flat = net.getStructure().getFlat();
    out.addSection("BASIC");
    out.addSubSection("PARAMS");
    out.addProperties(net.getProperties());
    out.addSubSection("NETWORK");

    out.writeProperty(BasicNetwork.TAG_BEGIN_TRAINING, flat.getBeginTraining());
    out.writeProperty(BasicNetwork.TAG_CONNECTION_LIMIT, flat.getConnectionLimit());
    out.writeProperty(BasicNetwork.TAG_CONTEXT_TARGET_OFFSET, flat.getContextTargetOffset());
    out.writeProperty(BasicNetwork.TAG_CONTEXT_TARGET_SIZE, flat.getContextTargetSize());
    out.writeProperty(BasicNetwork.TAG_END_TRAINING, flat.getEndTraining());
    out.writeProperty(BasicNetwork.TAG_HAS_CONTEXT, flat.getHasContext());
    out.writeProperty(PersistConst.INPUT_COUNT, flat.getInputCount());
    out.writeProperty(BasicNetwork.TAG_LAYER_COUNTS, flat.getLayerCounts());
    out.writeProperty(BasicNetwork.TAG_LAYER_FEED_COUNTS, flat.getLayerFeedCounts());
    out.writeProperty(BasicNetwork.TAG_LAYER_CONTEXT_COUNT, flat.getLayerContextCount());
    out.writeProperty(BasicNetwork.TAG_LAYER_INDEX, flat.getLayerIndex());
    out.writeProperty(PersistConst.OUTPUT, flat.getLayerOutput());
    out.writeProperty(PersistConst.OUTPUT_COUNT, flat.getOutputCount());
    out.writeProperty(BasicNetwork.TAG_WEIGHT_INDEX, flat.getWeightIndex());
    out.writeProperty(PersistConst.WEIGHTS, flat.getWeights());
    out.writeProperty(BasicNetwork.TAG_BIAS_ACTIVATION, flat.getBiasActivation());
    out.addSubSection("ACTIVATION");
    for (final ActivationFunction af : flat.getActivationFunctions()) {
      String sn = af.getClass().getSimpleName();
      // if this is an Encog class then only add the simple name, so it works with C#
      if (sn.startsWith("org.encog.")) {
        out.addColumn(sn);
      } else {
        out.addColumn(af.getClass().getName());
      }
      for (int i = 0; i < af.getParams().length; i++) {
        out.addColumn(af.getParams()[i]);
      }
      out.writeLine();
    }

    out.flush();
  }
  /** {@inheritDoc} */
  @Override
  public void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final BoltzmannMachine boltz = (BoltzmannMachine) obj;
    out.addSection("BOLTZMANN");
    out.addSubSection("PARAMS");
    out.addProperties(boltz.getProperties());
    out.addSubSection("NETWORK");
    out.writeProperty(PersistConst.WEIGHTS, boltz.getWeights());
    out.writeProperty(PersistConst.OUTPUT, boltz.getCurrentState().getData());
    out.writeProperty(PersistConst.NEURON_COUNT, boltz.getNeuronCount());

    out.writeProperty(PersistConst.THRESHOLDS, boltz.getThreshold());
    out.writeProperty(BoltzmannMachine.ANNEAL_CYCLES, boltz.getAnnealCycles());
    out.writeProperty(BoltzmannMachine.RUN_CYCLES, boltz.getRunCycles());
    out.writeProperty(PersistConst.TEMPERATURE, boltz.getTemperature());

    out.flush();
  }
  /**
   * Save the script to a stream.
   *
   * @param stream The output stream.
   */
  public final void save(final OutputStream stream) {
    final EncogWriteHelper out = new EncogWriteHelper(stream);
    saveSubSection(out, "HEADER", "DATASOURCE");
    saveConfig(out);

    if (this.script.getFields() != null) {
      saveData(out);
      saveNormalize(out);
    }

    saveSubSection(out, "RANDOMIZE", "CONFIG");
    saveSubSection(out, "CLUSTER", "CONFIG");
    saveSubSection(out, "BALANCE", "CONFIG");

    if (this.script.getSegregate().getSegregateTargets() != null) {
      saveSegregate(out);
    }
    saveSubSection(out, "GENERATE", "CONFIG");
    saveMachineLearning(out);
    saveTasks(out);
    out.flush();
  }
  /** {@inheritDoc} */
  @Override
  public void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final ART1 art1 = (ART1) obj;
    out.addSection("ART1");
    out.addSubSection("PARAMS");
    out.addProperties(art1.getProperties());
    out.addSubSection("NETWORK");

    out.writeProperty(ART.PROPERTY_A1, art1.getA1());
    out.writeProperty(ART.PROPERTY_B1, art1.getB1());
    out.writeProperty(ART.PROPERTY_C1, art1.getC1());
    out.writeProperty(ART.PROPERTY_D1, art1.getD1());
    out.writeProperty(PersistConst.PROPERTY_F1_COUNT, art1.getF1Count());
    out.writeProperty(PersistConst.PROPERTY_F2_COUNT, art1.getF2Count());
    out.writeProperty(ART.PROPERTY_NO_WINNER, art1.getNoWinner());
    out.writeProperty(ART.PROPERTY_L, art1.getL());
    out.writeProperty(ART.PROPERTY_VIGILANCE, art1.getVigilance());
    out.writeProperty(PersistConst.PROPERTY_WEIGHTS_F1_F2, art1.getWeightsF1toF2());
    out.writeProperty(PersistConst.PROPERTY_WEIGHTS_F2_F1, art1.getWeightsF2toF1());

    out.flush();
  }
  /** {@inheritDoc} */
  @Override
  public final void save(final OutputStream os, final Object obj) {
    final EncogWriteHelper out = new EncogWriteHelper(os);
    final BayesianNetwork b = (BayesianNetwork) obj;
    out.addSection("BAYES-NETWORK");
    out.addSubSection("BAYES-PARAM");
    String queryType = "";
    String queryStr = b.getClassificationStructure();

    if (b.getQuery() != null) {
      queryType = b.getQuery().getClass().getSimpleName();
    }

    out.writeProperty("queryType", queryType);
    out.writeProperty("query", queryStr);
    out.writeProperty("contents", b.getContents());
    out.addSubSection("BAYES-PROPERTIES");
    out.addProperties(b.getProperties());

    out.addSubSection("BAYES-TABLE");
    for (BayesianEvent event : b.getEvents()) {
      for (TableLine line : event.getTable().getLines()) {
        if (line == null) continue;
        StringBuilder str = new StringBuilder();
        str.append("P(");

        str.append(BayesianEvent.formatEventName(event, line.getResult()));

        if (event.getParents().size() > 0) {
          str.append("|");
        }

        int index = 0;
        boolean first = true;
        for (BayesianEvent parentEvent : event.getParents()) {
          if (!first) {
            str.append(",");
          }
          first = false;
          int arg = line.getArguments()[index++];
          if (parentEvent.isBoolean()) {
            if (arg == 0) {
              str.append("+");
            } else {
              str.append("-");
            }
          }
          str.append(parentEvent.getLabel());
          if (!parentEvent.isBoolean()) {
            str.append("=");
            if (arg >= parentEvent.getChoices().size()) {
              throw new BayesianError(
                  "Argument value " + arg + " is out of range for event " + parentEvent.toString());
            }
            str.append(parentEvent.getChoice(arg));
          }
        }
        str.append(")=");
        str.append(line.getProbability());
        str.append("\n");
        out.write(str.toString());
      }
    }

    out.flush();
  }