/// <summary> /// Converts the tree into an array based representation. The purpose /// of the array representation is that it takes up FAR LESS memory and /// allows for a larger popuplation. This comes at the expense of some /// compute time, however. /// </summary> /// <param name="FunctionSet"></param> public void ConvertToArray(IGPFunctionSet FunctionSet) { // // If the array already exists, reuse it. The reason it would already exist // is if the conversion to a tree was don't for fitness computations and not // for altering the tree sturcture. A simple optimization technique if (m_TreeArrayNew != null) { m_Root = null; return; } // // Allocate the nodes we need try { m_TreeArrayNew = new List <byte>(m_CountNodes); } catch (Exception) { System.Console.WriteLine("ConvertToArray: " + m_CountNodes); return; } // // Use a recursive technique to work through the nodes and get // them stored into the array m_ArrayPos = 0; StoreNode(m_Root, FunctionSet); // // Get rid of the tree m_Root = null; }
/// <summary> /// Kickoff method for converting the program from an array based representation /// back into the nice easy to use tree representation. /// </summary> /// <param name="FunctionSet"></param> /// <param name="ForFitness">If this is for fitness computations, don't remove the array, because /// we can save time on the ConvertToArray method later on.</param> public void ConvertToTree(IGPFunctionSet FunctionSet, bool ForFitness) { m_RPB.ConvertToTree(FunctionSet, ForFitness); foreach (GPProgramBranchADF adf in m_listADF) { adf.ConvertToTree(FunctionSet, ForFitness); } }
/// <summary> /// Kickoff method for converting the program tree representation into /// a nice compact array representation. /// </summary> /// <param name="FunctionSet">List of user defined functions, the index /// of the function is used for as the array representation</param> public void ConvertToArray(IGPFunctionSet FunctionSet) { m_RPB.ConvertToArray(FunctionSet); foreach (GPProgramBranchADF adf in m_listADF) { adf.ConvertToArray(FunctionSet); } // // TODO: Should do this for ADLs and ADRs also, haven't yet done it // because use of those is very low right now. }
/// <summary> /// Constructor that accepts an XML string to work from /// </summary> /// <param name="ProgramXML"></param> /// <param name="FunctionSet"></param> public GPProgramReaderXML(String ProgramXML, IGPFunctionSet FunctionSet) { // // Save the function set m_FunctionSet = FunctionSet; // // Create a DOM document for parsing m_DocProgram = new XmlDocument(); m_DocProgram.LoadXml(ProgramXML); m_DocProgram.Normalize(); }
/// <summary> /// Restores the program from the array representation back into a tree structure. /// </summary> /// <param name="FunctionSet"></param> /// <param name="ForFitness"></param> public void ConvertToTree(IGPFunctionSet FunctionSet, bool ForFitness) { // // Recursively build the tree out of the array m_ArrayPos = 0; GPNode root = ConvertNode(FunctionSet); m_Root = root; // // Remove the array - unless this is for a fitness computation if (!ForFitness) { m_TreeArrayNew = null; } this.UpdateStats(); }
/// <summary> /// Restores a node from the array representation back into a tree representation /// </summary> /// <param name="FunctionSet"></param> /// <returns>Reference to the converted tree</returns> public GPNode ConvertNode(IGPFunctionSet FunctionSet) { // // Determine the type of the node // < 200 : User Defined function // 200 to 210 : Terminal // 253 : ADR // 254 : ADL // 255 : ADF if (m_TreeArrayNew[m_ArrayPos] == 255) { m_ArrayPos++; byte WhichADF = m_TreeArrayNew[m_ArrayPos++]; byte NumberArgs = m_TreeArrayNew[m_ArrayPos++]; GPNodeFunctionADF NodeNew = new GPNodeFunctionADF(WhichADF, NumberArgs); // // Build up the children before returning for (byte Child = 0; Child < NumberArgs; Child++) { NodeNew.Children.Add(ConvertNode(FunctionSet)); } return(NodeNew); } else if (m_TreeArrayNew[m_ArrayPos] == 254) { m_ArrayPos++; byte WhichADL = m_TreeArrayNew[m_ArrayPos++]; byte NumberArgs = m_TreeArrayNew[m_ArrayPos++]; GPNodeFunctionADL NodeNew = new GPNodeFunctionADL(WhichADL, NumberArgs); // // Build up the children before returning for (byte Child = 0; Child < NumberArgs; Child++) { NodeNew.Children.Add(ConvertNode(FunctionSet)); } return(NodeNew); } else if (m_TreeArrayNew[m_ArrayPos] == 253) { m_ArrayPos++; byte WhichADR = m_TreeArrayNew[m_ArrayPos++]; byte NumberArgs = m_TreeArrayNew[m_ArrayPos++]; GPNodeFunctionADR NodeNew = new GPNodeFunctionADR(WhichADR, NumberArgs); // // Build up the children before returning for (byte Child = 0; Child < NumberArgs; Child++) { NodeNew.Children.Add(ConvertNode(FunctionSet)); } return(NodeNew); } else if (m_TreeArrayNew[m_ArrayPos] < 200) { GPNodeFunction NodeNew = (GPNodeFunction)((GPNodeFunction)FunctionSet[m_TreeArrayNew[m_ArrayPos++]]).Clone(); // // Build up this node's children first byte ChildCount = m_TreeArrayNew[m_ArrayPos++]; for (byte Child = 0; Child < ChildCount; Child++) { NodeNew.Children.Add(ConvertNode(FunctionSet)); } return(NodeNew); } else // Terminal { switch (m_TreeArrayNew[m_ArrayPos++]) { case 200: byte WhichADFParam = m_TreeArrayNew[m_ArrayPos++]; GPNodeTerminalADFParam NodeADF = new GPNodeTerminalADFParam(WhichADFParam); return(NodeADF); case 201: byte WhichUserDefined = m_TreeArrayNew[m_ArrayPos++]; GPNodeTerminalUserDefined NodeUser = new GPNodeTerminalUserDefined(WhichUserDefined); return(NodeUser); case 202: double dValue; unsafe { byte *ptr = (byte *)&dValue; for (int pos = 0; pos < sizeof(double); pos++) { ptr[pos] = m_TreeArrayNew[m_ArrayPos++]; } } GPNodeTerminalDouble NodeDouble = new GPNodeTerminalDouble(dValue); return(NodeDouble); case 203: int nValue; unsafe { byte *ptr = (byte *)&nValue; for (int pos = 0; pos < sizeof(int); pos++) { ptr[pos] = m_TreeArrayNew[m_ArrayPos++]; } } GPNodeTerminalInteger NodeInteger = new GPNodeTerminalInteger(nValue); return(NodeInteger); } } // // TODO: Throw an exception, instead of this lazy crap! :) return(null); }
/// <summary> /// Converts a tree node into an array based representation. For functions /// an byte lookup is used into the FunctionSet, for terminals, the type /// is recorded along with whatever extra data may be needed. /// TODO: Get rid of the unsafe code. I know there is a bit conversion /// function, I just couldn't find it quickly. /// </summary> /// <param name="Node">The node to convert</param> /// <param name="FunctionSet"></param> private void StoreNode(GPNode Node, IGPFunctionSet FunctionSet) { // // Figure out what kind of node we have and store it accordingly. if (Node is GPNodeFunction) { GPNodeFunction NodeFunction = (GPNodeFunction)Node; if (NodeFunction is GPNodeFunctionADF) { GPNodeFunctionADF adf = (GPNodeFunctionADF)NodeFunction; // // For an ADF node,record it as value 255 and then store the which // ADF it refers to and the number of arguments. m_TreeArrayNew.Add((byte)255); m_TreeArrayNew.Add((byte)adf.WhichFunction); m_TreeArrayNew.Add(adf.NumberArgs); } else if (NodeFunction is GPNodeFunctionADL) { GPNodeFunctionADL adl = (GPNodeFunctionADL)NodeFunction; // // For an ADL node,record it as value 254 and then store the which // ADL it refers to and the number of arguments. m_TreeArrayNew.Add((byte)254); m_TreeArrayNew.Add((byte)adl.WhichFunction); m_TreeArrayNew.Add(adl.NumberArgs); } else if (NodeFunction is GPNodeFunctionADR) { GPNodeFunctionADR adr = (GPNodeFunctionADR)NodeFunction; // // For an ADR node,record it as value 253 and then store the which // ADR it refers to and the number of arguments. m_TreeArrayNew.Add((byte)253); m_TreeArrayNew.Add((byte)adr.WhichFunction); m_TreeArrayNew.Add(adr.NumberArgs); } else { // // Store the index of the function and then the number of children // for this function m_TreeArrayNew.Add((byte)FunctionSet.IndexOfKey(NodeFunction.ToStringUpper())); m_TreeArrayNew.Add((byte)((GPNodeFunction)Node).Children.Count); } // // Store each of the children foreach (GPNode NodeChild in NodeFunction.Children) { StoreNode(NodeChild, FunctionSet); } } else // Terminal Node { // // Depending upon the type of the terminal, set the appropriate value if (Node is GPNodeTerminalADFParam) { m_TreeArrayNew.Add(200); m_TreeArrayNew.Add((byte)((GPNodeTerminalADFParam)Node).WhichParameter); } else if (Node is GPNodeTerminalUserDefined) { m_TreeArrayNew.Add(201); m_TreeArrayNew.Add((byte)((GPNodeTerminalUserDefined)Node).WhichUserDefined); } else if (Node is GPNodeTerminalDouble) { m_TreeArrayNew.Add(202); double dValue = ((GPNodeTerminalDouble)Node).Value; unsafe { byte *ptr = (byte *)&dValue; for (int pos = 0; pos < sizeof(double); pos++) { m_TreeArrayNew.Add(ptr[pos]); } } } else if (Node is GPNodeTerminalInteger) { m_TreeArrayNew.Add(203); int dValue = ((GPNodeTerminalInteger)Node).Value; unsafe { byte *ptr = (byte *)&dValue; for (int pos = 0; pos < sizeof(int); pos++) { m_TreeArrayNew.Add(ptr[pos]); } } } } }
/// <summary> /// Gets the settings for an individual modeler prepared. This function is /// intended to be called asynchronously. /// </summary> /// <param name="iServer"></param> /// <param name="iModeler"></param> /// <param name="Training"></param> /// <returns></returns> private bool InitializeModeler(IGPServer iServer, IGPModeler iModeler, GPModelingData Training) { // // The data we want to send is data appropriate for modeling. Time Series // data needs to be transformed for the modeler. if (m_DELReportStatus != null) { m_DELReportStatus("Loading training data..."); } iModeler.Training = Training.TrainingForModeling( m_Profile.ModelType.InputDimension, m_Profile.ModelType.PredictionDistance); // // Prepare the function set for each server if (m_DELReportStatus != null) { m_DELReportStatus("Transmitting user defined functions..."); } IGPFunctionSet iFunctionSet = iServer.FunctionSet; // // Use a client side sponsor for this function set // TODO: This sponsor should really come from the server we obtained // the function set interface from. The reason it currently isn't, is // because the whole "lease lifetime" thing isn't fully thought out yet // in this application. ILease LeaseInfo = (ILease)((MarshalByRefObject)iFunctionSet).GetLifetimeService(); LeaseInfo.Register(m_FunctionSetSponsor); // // Let's go ahead and assign the same lease sponsor to the modeler LeaseInfo = (ILease)((MarshalByRefObject)iModeler).GetLifetimeService(); LeaseInfo.Register(m_ModelerSponsor); #if GPLOG GPLog.ReportLine("Loading UDFs...", true); #endif foreach (string FunctionName in m_Profile.FunctionSet) { #if GPLOG GPLog.ReportLine(" UDF: " + FunctionName, false); #endif // // Load the Function from the database short FunctionArity = 0; bool TerminalParameters = false; String FunctionCode = ""; if (GPDatabaseUtils.LoadFunctionFromDB(FunctionName, ref FunctionArity, ref TerminalParameters, ref FunctionCode, GPEnums.LANGUAGEID_CSHARP)) { // // Add it to the function set iFunctionSet.AddFunction(FunctionName, FunctionArity, TerminalParameters, FunctionCode); } } iFunctionSet.UseMemory = m_Profile.ModelingProfile.UseMemory; // // Assign it to the modeler iModeler.FunctionSet = iFunctionSet; #if GPLOG GPLog.Report("Transmitting fitness function...", true); #endif // // Pass the fitness function to each modeler if (m_DELReportStatus != null) { m_DELReportStatus("Transmitting fitness function..."); } String FitnessFunction = GPDatabaseUtils.FieldValue(m_Profile.FitnessFunctionID, "tblFitnessFunction", "Code"); iModeler.FitnessFunction = FitnessFunction; #if GPLOG GPLog.ReportLine("...Complete", false); #endif // // Transmit the profile/modeling settings if (m_DELReportStatus != null) { m_DELReportStatus("Transmitting modeling parameters..."); } iModeler.Profile = m_Profile.ModelingProfile; // // Send over which ADF and ADLs to evolve foreach (byte adf in m_Profile.m_ADFSet) { iModeler.AddADF(adf); } foreach (byte adl in m_Profile.m_ADLSet) { iModeler.AddADL(adl); } foreach (byte adr in m_Profile.m_ADRSet) { iModeler.AddADR(adr); } return(true); }