Marshalling Populations to XML

[JGAP Home]

For many applications, some sort of marshalling mechanism can be very useful. Perhaps it's desirable to save the current population to disk for later so that evolution can continue at another time, or perhaps it's necessary to send populations over a network as part of a distributed application. JGAP comes with facilities for representing genotypes, chromosomes, and even individual genes as XML documents and/or elements. This process is called marshalling. And, of course, JGAP can later unmarshall those objects from their respective XML representations. This document discusses the org.jgap.xml.XMLManager class, which is responsible for these facilities, and provides an example of its use.

Parser-specific Implementations

As a bit of an aside, it should be noted that, while the creation and traversing of an XML document object (DOM) has been standardized by the W3C, the actual generation of an XML file or other representation from a DOM object will not be standardized until the DOM Level 3 specification is finalized. Until then, each XML parser provides its own implementation-specific mechanism. As a result, JGAP will generate a DOM object for you from a genetic entity, but the actual process of rendering that DOM object to a file or other medium is up to you. An example of this process is provided in this document using the Xerces Java 2 parser, which is a free, open-source XML parser provided by the Apache foundation.

An Example

Let us say, for our example, that we are creating a chess program that, as one of its many selling points, will evolve its strategy to match any opponent. To implement this in our hypothetical program, we have of course decided to use JGAP to create a genetic algorithm that manages the chess AI. It's not enough, however, for us to simply evolve the AI strategy to some acceptable point at the factory and then ship out the program with a frozen strategy. Since we've promised that our AI will adapt to its opponents, it's necessary for the AI strategy to continue evolving as the game is played. This inevitably means that we need some mechanism for storing our current genetic state in between program runs. Fortunately, JGAP provides the XMLManager class to help us out with this. Even more fortunate is that it's very simple to use. Here's the code:

/**
 * Saves the given population to the given filename as an XML
 * file. The population can later be reconstructed from the
 * XML file through a call to the getSavedStrategyState() method.
 *
 * @param a_currentPopulation The population to save.
 * @param a_saveToFilename The full path to the file where the
 *                         XML representation should be saved.
 */
public static saveStrategyState( Genotype a_currentPopulation,
                                 string a_saveToFilename )
              throws Exception
{
    // Convert the Genotype to a DOM object.
    // -------------------------------------
    Document xmlRepresentation =
        XMLManager.representGenotypeAsDocument( a_currentPopulation );

    // Now write that DOM to disk as an XML file. This is all
    // parser-specific. We're assuming the use of the Xerces Java 2
    // parser for this example.
    // ------------------------------------------------------------
    Writer documentWriter = new FileWriter( a_saveToFilename );

    OutputFormat formatting =
        new OutputFormat( genotypeDoc, "UTF-8", true );

    SerializerFactory factory =
        SerializerFactory.getSerializerFactory( Method.XML );

    Serializer genericSerializer =
        factory.makeSerializer( documentWriter, formatting );

    DOMSerializer documentSerializer =
        genericSerializer.asDOMSerializer();

    documentSerializer.serialize( genotypeDoc );
    documentWriter.close();
}


/**
 * Recreates a population that was earlier saved to an XML file through
 * the saveStrategyState() method.
 *
 * @param a_activeConfiguration The current active Configuration object.
 * @param a_savedToFilename The full path of the file where the XML
 *                          representation was saved.
 *
 * @return A new Genotype instance that is populated from the XML
 *         representation found in the given file.
 */
public static Genotype getSavedStrategyState(
                           Configuration a_activeConfiguration,
                           String a_savedToFilename )
                       throws Exception
{
    // Read the saved xml file into a DOM object.
    // ------------------------------------------
    Reader documentReader = new FileReader( a_savedToFilename );
    InputSource documentSource = new InputSource( documentReader );
    DocumentBuilder builder =
        DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document genotypeDocument = builder.parse( documentSource );


    // Convert the DOM object back to a Genotype
    // -----------------------------------------
    return XMLManager.getGenotypeFromDocument( a_activeConfiguration,
                                               genotypeDocument );
}

As can be seen from the above, interaction with the JGAP XMLManager to create a DOM object from a Genotype--or recreate a Genotype from a DOM object--can typically be confined to a line or two of code. Most of the work involves getting that DOM to disk (and back again), which may be easier or more difficult depending on which parser you use. When the DOM Level 3 standard is finalized, it is likely that the facilities of the XMLManager class will be expanded to encompass this entire process.


[JGAP Home]

SourceForge Logo