/// <summary> /// Perform one operation. /// </summary> public void PerformTask() { bool success = false; int tries = _train.MaxOperationErrors; do { try { // choose an evolutionary operation (i.e. crossover or a type of // mutation) to use IEvolutionaryOperator opp = _train.Operators .PickMaxParents(_rnd, _species.Members.Count); _children[0] = null; // prepare for either sexual or asexual reproduction either way, // we need at least one parent, which is the first parent. // // Chose the first parent, there must be at least one genome in // this species _parents[0] = ChooseParent(); // if the number of individuals in this species is only // one then we can only clone and perhaps mutate, otherwise use // the crossover probability to determine if we are to use // sexual reproduction. if (opp.ParentsNeeded > 1) { int numAttempts = 5; _parents[1] = ChooseParent(); while (_parents[0] == _parents[1] && numAttempts-- > 0) { _parents[1] = ChooseParent(); } // success, perform crossover if (_parents[0] != _parents[1]) { opp.PerformOperation(_rnd, _parents, 0, _children, 0); } } else { // clone a child (asexual reproduction) opp.PerformOperation(_rnd, _parents, 0, _children, 0); _children[0].Population = _parents[0].Population; } // process the new child foreach (IGenome child in _children) { if (child != null) { child.Population = _parents[0].Population; child.BirthGeneration = _train.IterationNumber; _train.CalculateScore(child); if (!_train.AddChild(child)) { return; } success = true; } } } catch (AIFHError) { tries--; if (tries < 0) { throw new AIFHError( "Could not perform a successful genetic operaton after " + _train.MaxOperationErrors + " tries."); } } catch (Exception t) { if (!_train.IgnoreExceptions) { throw; } } } while (!success); }