diff --git a/generation.go b/generation.go index 7c09a1c..b4707b4 100644 --- a/generation.go +++ b/generation.go @@ -55,7 +55,7 @@ func populatePool(pool []sequenceInfo, nextChromosome chan string, geneSet strin distinctPool := make(map[string]bool, len(pool)) itemGenes := generateParent(nextChromosome, geneSet, numberOfChromosomes, numberOfGenesPerChromosome) initialStrategy := strategyInfo{name: "initial "} - pool[0] = sequenceInfo{itemGenes, getFitness(itemGenes), initialStrategy} + pool[0] = sequenceInfo{genes: itemGenes, fitness: getFitness(itemGenes), strategy: initialStrategy} for i := 1; i < len(pool); { itemGenes = generateParent(nextChromosome, geneSet, numberOfChromosomes, numberOfGenesPerChromosome) @@ -65,7 +65,7 @@ func populatePool(pool []sequenceInfo, nextChromosome chan string, geneSet strin } distinctPool[itemGenes] = true - pool[i] = sequenceInfo{itemGenes, getFitness(itemGenes), initialStrategy} + pool[i] = sequenceInfo{genes: itemGenes, fitness: getFitness(itemGenes), strategy: initialStrategy} insertionSort(pool, compareFitnesses, i) i++ diff --git a/genetic.go b/genetic.go index 8e1145c..26127df 100644 --- a/genetic.go +++ b/genetic.go @@ -85,7 +85,7 @@ func (solver *Solver) GetBestUsingHillClimbing(getFitness func(string) int, distinctPool[childGenes] = true fitness := getFitness(childGenes) - child := sequenceInfo{childGenes, fitness, initialStrategy} + child := sequenceInfo{genes: childGenes, fitness: fitness, strategy: initialStrategy} if len(newPool) < solver.maxPoolSize { newPool = append(newPool, child) } else { @@ -166,17 +166,20 @@ func (solver *Solver) getBestWithInitialParent(getFitness func(string) int, distinctChildren := make(map[string]bool, len(solver.pool)) distinctChildrenFitnesses := populateDistinctPoolFitnessesMap(solver.pool) - swapPoolsIfNecessary := func() { - if len(distinctChildren) >= solver.maxPoolSize && - len(distinctChildrenFitnesses) > 3 { + quit := make(chan bool) + + promoteChildrenIfFull := func() { + if len(children) >= 20 || len(children) >= 10 && time.Since(start).Seconds() > solver.MaxSecondsToRunWithoutImprovement/2 { if solver.PrintDiagnosticInfo { fmt.Print(">") solver.needNewlineBeforeDisplay = true } solver.poolLock.Lock() + solver.distinctPoolLock.Lock() solver.pool = children solver.distinctPool = distinctChildren + solver.distinctPoolLock.Unlock() solver.poolLock.Unlock() bestParent := solver.pool[0] @@ -191,11 +194,64 @@ func (solver *Solver) getBestWithInitialParent(getFitness func(string) int, } } - updateIfIsImprovement := func(child sequenceInfo) { - if solver.shouldAddChild(child) { - if solver.updatePools(child, children, distinctChildren, distinctChildrenFitnesses, display) { - swapPoolsIfNecessary() - solver.incrementStrategyUseCount(child.strategy.index) + updatePools := func(child *sequenceInfo) bool { + addToChildren := func(item *sequenceInfo) { + if len(children) < solver.maxPoolSize && + (len(distinctChildrenFitnesses) < 4 || + (*item).fitness == children[len(children)-1].fitness) { + + children = append(children, *item) + + if solver.PrintDiagnosticInfo { + fmt.Print(".") + solver.needNewlineBeforeDisplay = true + } + insertionSort(children, solver.childFitnessIsSameOrBetter, len(children)-1) + } else if solver.childFitnessIsSameOrBetter(*item, children[len(children)-1]) { + children[len(children)-1] = *item + insertionSort(children, solver.childFitnessIsSameOrBetter, len(children)-1) + } + + distinctChildren[(*item).genes] = true + distinctChildrenFitnesses[(*item).fitness] = true + } + addToChildren(child) + + if solver.childFitnessIsBetter(*child, solver.pool[0]) { + solver.printNewlineIfNecessary() + if solver.PrintStrategyUsage { + fmt.Print((*child).strategy.name) + } + display(*child) + + if solver.pool[0].genes == (*(*child).parent).genes { + solver.successParentIsBestParentCount++ + } + solver.numberOfImprovements++ + + solver.pool[0] = *child + if solver.PrintDiagnosticInfo { + fmt.Print("+") + solver.needNewlineBeforeDisplay = true + } + + solver.pool[len(solver.pool)-1] = *child + insertionSort(solver.pool, solver.childFitnessIsSameOrBetter, len(solver.pool)-1) + + if !distinctChildren[(*(*child).parent).genes] { + addToChildren(child.parent) + } + + return true + } + + return false + } + + updateIfIsImprovement := func(child *sequenceInfo) { + if solver.shouldAddChild(child, getFitness) { + if updatePools(child) { + solver.incrementStrategyUseCount((*child).strategy.index) start = time.Now() } } @@ -204,62 +260,39 @@ func (solver *Solver) getBestWithInitialParent(getFitness func(string) int, timeout := make(chan bool, 1) go func() { for { - time.Sleep(250 * time.Millisecond) - timeout <- true + time.Sleep(1 * time.Millisecond) + select { + case timeout <- true: + case <-quit: + quit <- true + } } + close(timeout) }() defer func() { + quit <- true for _, child := range children { solver.pool = append(solver.pool, child) } }() for { - // prefer successful strategies minStrategySuccess := solver.nextRand(solver.maxStrategySuccess) - anyResultsReceived := false for index := 0; index < len(solver.strategies); index++ { - if solver.strategies[index].successCount >= minStrategySuccess { - select { - case child := <-solver.strategies[index].results: - updateIfIsImprovement(child) - anyResultsReceived = true - case <-timeout: - if time.Since(start).Seconds() >= solver.MaxSecondsToRunWithoutImprovement { - return solver.pool[0] - } - default: - } - } - } - - if anyResultsReceived { - continue - } - - // but take any strategy when it gets tough to find children - select { - case child := <-solver.strategies[0].results: - updateIfIsImprovement(child) - case child := <-solver.strategies[1].results: - updateIfIsImprovement(child) - case child := <-solver.strategies[2].results: - updateIfIsImprovement(child) - case child := <-solver.strategies[3].results: - updateIfIsImprovement(child) - case child := <-solver.strategies[4].results: - updateIfIsImprovement(child) - case <-timeout: - if solver.PrintDiagnosticInfo { - fmt.Print("_") - solver.needNewlineBeforeDisplay = true + if solver.strategies[index].successCount < minStrategySuccess { + continue } - if time.Since(start).Seconds() >= solver.MaxSecondsToRunWithoutImprovement { - return solver.pool[0] + select { + case child := <-solver.strategies[index].results: + updateIfIsImprovement(child) + case <-timeout: + if time.Since(start).Seconds() >= solver.MaxSecondsToRunWithoutImprovement { + return solver.pool[0] + } + promoteChildrenIfFull() } - break } } return solver.pool[0] @@ -306,7 +339,7 @@ func (solver *Solver) initialize(geneSet string, numberOfGenesPerChromosome int, if solver.MaxRoundsWithoutImprovement == 0 { solver.MaxRoundsWithoutImprovement = 2 } - solver.rand = createRandomNumberGenerator(solver.RandSeed) + solver.random = createRandomNumberGenerator(solver.RandSeed) solver.ensureMaxSecondsToRunIsValid() solver.createFitnessComparisonFunctions() solver.initializeChannels(geneSet, numberOfGenesPerChromosome) @@ -327,10 +360,30 @@ func (solver *Solver) initializePool(numberOfChromosomes, numberOfGenesPerChromo solver.pool = make([]sequenceInfo, solver.maxPoolSize, solver.maxPoolSize) solver.pool[0] = initialParent solver.distinctPool = populatePool(solver.pool, solver.nextChromosome, geneSet, numberOfChromosomes, numberOfGenesPerChromosome, solver.childFitnessIsBetter, getFitness) + + solver.numberOfImprovements = 1 + solver.randomParent = make(chan *sequenceInfo, 10) + go func() { + for { + select { + case <-solver.quit: + solver.quit <- true + return + default: + useBestParent := solver.random.Intn(solver.numberOfImprovements) <= solver.successParentIsBestParentCount + if useBestParent { + parent := solver.pool[0] + solver.randomParent <- &parent + } + parent := solver.pool[solver.random.Intn(len(solver.pool))] + solver.randomParent <- &parent + } + } + }() } func (solver *Solver) nextRand(limit int) int { - return solver.rand.Intn(limit) + return solver.random.Intn(limit) } func (solver *Solver) printNewlineIfNecessary() { @@ -345,35 +398,35 @@ func (solver *Solver) printStrategyUsage() { return } - strategySuccessSum := 0 - for _, strategy := range solver.strategies { - strategySuccessSum += strategy.successCount - } - fmt.Println("\nstrategy usage:") for _, strategy := range solver.strategies { fmt.Println( strategy.name, "\t", strategy.successCount, "\t", - 100.0*strategy.successCount/strategySuccessSum, "%") + 100.0*strategy.successCount/solver.numberOfImprovements, "%") } fmt.Println() + + fmt.Println("\nNew champions were children of the reigning champion", + 100*solver.successParentIsBestParentCount/solver.numberOfImprovements, + "% of the time.\n") } -func (solver *Solver) shouldAddChild(child sequenceInfo) bool { - if solver.inPool(child.genes) { +func (solver *Solver) shouldAddChild(child *sequenceInfo, getFitness func(string) int) bool { + if solver.inPool((*child).genes) { return false } - if !solver.childFitnessIsSameOrBetter(child, solver.pool[len(solver.pool)-1]) { + (*child).fitness = getFitness((*child).genes) + if !solver.childFitnessIsSameOrBetter(*child, solver.pool[len(solver.pool)-1]) { return false } - if child.fitness == solver.pool[len(solver.pool)-1].fitness { + if (*child).fitness == solver.pool[len(solver.pool)-1].fitness { if len(solver.pool) < solver.maxPoolSize { - solver.pool = append(solver.pool, child) + solver.pool = append(solver.pool, *child) } else { - solver.pool[len(solver.pool)-1] = child + solver.pool[len(solver.pool)-1] = *child insertionSort(solver.pool, solver.childFitnessIsSameOrBetter, len(solver.pool)-1) } @@ -383,47 +436,6 @@ func (solver *Solver) shouldAddChild(child sequenceInfo) bool { return true } -func (solver *Solver) updatePools(child sequenceInfo, children []sequenceInfo, distinctChildren map[string]bool, distinctChildrenFitnesses map[int]bool, display func(sequenceInfo)) bool { - if len(children) < solver.maxPoolSize && - (len(distinctChildrenFitnesses) < 4 || - child.fitness == children[len(children)-1].fitness) { - - children = append(children, child) - - if solver.PrintDiagnosticInfo { - fmt.Print(".") - solver.needNewlineBeforeDisplay = true - } - } else { - children[len(children)-1] = child - } - - insertionSort(children, solver.childFitnessIsSameOrBetter, len(children)-1) - - distinctChildren[child.genes] = true - distinctChildrenFitnesses[child.fitness] = true - - if solver.childFitnessIsBetter(child, solver.pool[0]) { - solver.printNewlineIfNecessary() - if solver.PrintStrategyUsage { - fmt.Print(child.strategy.name) - } - display(child) - solver.pool[0] = child - if solver.PrintDiagnosticInfo { - fmt.Print("+") - solver.needNewlineBeforeDisplay = true - } - - solver.pool[len(solver.pool)-1] = child - insertionSort(solver.pool, solver.childFitnessIsSameOrBetter, len(solver.pool)-1) - - return true - } - - return false -} - func populateDistinctPoolFitnessesMap(pool []sequenceInfo) map[int]bool { distinctChildrenFitnesses := make(map[int]bool, len(pool)) distinctChildrenFitnesses[pool[0].fitness] = true diff --git a/strategies.go b/strategies.go index 5c7e566..e7972ba 100644 --- a/strategies.go +++ b/strategies.go @@ -5,7 +5,7 @@ import ( "strings" ) -func (solver *Solver) getMutationStrategyResultChannel() chan sequenceInfo { +func (solver *Solver) getMutationStrategyResultChannel() chan *sequenceInfo { mutateStrategyResults := solver.strategies[0].results for _, strategy := range solver.strategies { if strings.Contains(strategy.name, "mutate") { @@ -29,10 +29,12 @@ func (solver *Solver) crossover(strategy strategyInfo, numberOfGenesPerChromosom break } - parentA := solver.pool[random.Intn(len(solver.pool))].genes - parentB := solver.pool[0].genes + parentA := <-solver.randomParent + parentAgenes := (*parentA).genes + parentB := <-solver.randomParent + parentBgenes := (*parentB).genes - if len(parentA) == 1 || len(parentB) == 1 { + if len(parentAgenes) == 1 || len(parentBgenes) == 1 { select { case <-solver.quit: solver.quit <- true @@ -43,29 +45,27 @@ func (solver *Solver) crossover(strategy strategyInfo, numberOfGenesPerChromosom } } - sourceStart := random.Intn((len(parentB)-1)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome - destinationStart := random.Intn((len(parentA)-1)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome - maxLength := min(len(parentA)-destinationStart, len(parentB)-sourceStart) + sourceStart := random.Intn((len(parentBgenes)-1)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome + destinationStart := random.Intn((len(parentAgenes)-1)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome + maxLength := min(len(parentAgenes)-destinationStart, len(parentBgenes)-sourceStart) length := (1 + random.Intn(maxLength/numberOfGenesPerChromosome-1)) * numberOfGenesPerChromosome - childGenes := bytes.NewBuffer(make([]byte, 0, max(len(parentA), len(parentB)))) + childGenes := bytes.NewBuffer(make([]byte, 0, max(len(parentAgenes), len(parentBgenes)))) if destinationStart > 0 { - childGenes.WriteString(parentA[0:destinationStart]) + childGenes.WriteString(parentAgenes[0:destinationStart]) } - childGenes.WriteString(parentB[sourceStart : sourceStart+length]) + childGenes.WriteString(parentBgenes[sourceStart : sourceStart+length]) - if childGenes.Len() < len(parentA) { - childGenes.WriteString(parentA[childGenes.Len():len(parentA)]) + if childGenes.Len() < len(parentAgenes) { + childGenes.WriteString(parentAgenes[childGenes.Len():len(parentAgenes)]) } - child := sequenceInfo{genes: childGenes.String(), strategy: strategy} - child.fitness = getFitness(child.genes) + child := sequenceInfo{genes: childGenes.String(), strategy: strategy, parent: parentA} select { - case strategy.results <- child: - continue + case strategy.results <- &child: case <-solver.quit: solver.quit <- true return @@ -85,20 +85,17 @@ func (solver *Solver) mutate(strategy strategyInfo, numberOfGenesPerChromosome i break } - useBestParent := random.Intn(100) == 0 - parent := solver.pool[0].genes - if !useBestParent { - parent = solver.pool[random.Intn(len(solver.pool))].genes - } + parent := <-solver.randomParent + parentGenes := (*parent).genes - parentIndex := random.Intn(len(parent)) + parentIndex := random.Intn(len(parentGenes)) - childGenes := bytes.NewBuffer(make([]byte, 0, len(parent))) + childGenes := bytes.NewBuffer(make([]byte, 0, len(parentGenes))) if parentIndex > 0 { - childGenes.WriteString(parent[:parentIndex]) + childGenes.WriteString(parentGenes[:parentIndex]) } - currentGene := parent[parentIndex : parentIndex+1] + currentGene := parentGenes[parentIndex : parentIndex+1] for { gene := <-solver.nextGene @@ -111,16 +108,14 @@ func (solver *Solver) mutate(strategy strategyInfo, numberOfGenesPerChromosome i } } - if parentIndex+1 < len(parent) { - childGenes.WriteString(parent[parentIndex+1:]) + if parentIndex+1 < len(parentGenes) { + childGenes.WriteString(parentGenes[parentIndex+1:]) } - child := sequenceInfo{genes: childGenes.String(), strategy: strategy} - child.fitness = getFitness(child.genes) + child := sequenceInfo{genes: childGenes.String(), strategy: strategy, parent: parent} select { - case strategy.results <- child: - continue + case strategy.results <- &child: case <-solver.quit: solver.quit <- true return @@ -141,13 +136,10 @@ func (solver *Solver) reverse(strategy strategyInfo, numberOfGenesPerChromosome break } - useBestParent := random.Intn(100) == 0 - parent := solver.pool[0].genes - if !useBestParent { - parent = solver.pool[random.Intn(len(solver.pool))].genes - } + parent := <-solver.randomParent + parentGenes := (*parent).genes - if len(parent) == 1 { + if len(parent.genes) == 1 { select { case <-solver.quit: solver.quit <- true @@ -158,21 +150,21 @@ func (solver *Solver) reverse(strategy strategyInfo, numberOfGenesPerChromosome } } - reversePointA := random.Intn(len(parent)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome - reversePointB := random.Intn(len(parent)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome - for ; reversePointA == reversePointB; reversePointB = random.Intn(len(parent)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome { + reversePointA := random.Intn(len(parentGenes)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome + reversePointB := random.Intn(len(parentGenes)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome + for ; reversePointA == reversePointB; reversePointB = random.Intn(len(parentGenes)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome { } min, max := sort(reversePointA, reversePointB) fragments := make([]string, max-min) for i := min; i < max; i += numberOfGenesPerChromosome { - fragments[i-min] = parent[i : i+numberOfGenesPerChromosome] + fragments[i-min] = parentGenes[i : i+numberOfGenesPerChromosome] } - childGenes := bytes.NewBuffer(make([]byte, 0, len(parent))) + childGenes := bytes.NewBuffer(make([]byte, 0, len(parentGenes))) if min > 0 { - childGenes.WriteString(parent[0:min]) + childGenes.WriteString(parentGenes[0:min]) } reverseArray(fragments) @@ -180,16 +172,14 @@ func (solver *Solver) reverse(strategy strategyInfo, numberOfGenesPerChromosome childGenes.WriteString(fragment) } - if childGenes.Len() < len(parent) { - childGenes.WriteString(parent[childGenes.Len():len(parent)]) + if childGenes.Len() < len(parentGenes) { + childGenes.WriteString(parentGenes[childGenes.Len():len(parentGenes)]) } - child := sequenceInfo{genes: childGenes.String(), strategy: strategy} - child.fitness = getFitness(child.genes) + child := sequenceInfo{genes: childGenes.String(), strategy: strategy, parent: parent} select { - case strategy.results <- child: - continue + case strategy.results <- &child: case <-solver.quit: solver.quit <- true return @@ -210,13 +200,10 @@ func (solver *Solver) shift(strategy strategyInfo, numberOfGenesPerChromosome in break } - useBestParent := random.Intn(100) == 0 - parent := solver.pool[0].genes - if !useBestParent { - parent = solver.pool[random.Intn(len(solver.pool))].genes - } + parent := <-solver.randomParent + parentGenes := (*parent).genes - if len(parent) < numberOfGenesPerChromosome+1 { + if len(parent.genes) < numberOfGenesPerChromosome+1 { select { case <-solver.quit: solver.quit <- true @@ -228,14 +215,14 @@ func (solver *Solver) shift(strategy strategyInfo, numberOfGenesPerChromosome in } shiftRight := random.Intn(2) == 1 - segmentStart := random.Intn((len(parent)-numberOfGenesPerChromosome)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome - segmentCount := 1 + random.Intn((len(parent)-segmentStart+numberOfGenesPerChromosome)/numberOfGenesPerChromosome-1) + segmentStart := random.Intn((len(parentGenes)-numberOfGenesPerChromosome)/numberOfGenesPerChromosome) * numberOfGenesPerChromosome + segmentCount := 1 + random.Intn((len(parentGenes)-segmentStart+numberOfGenesPerChromosome)/numberOfGenesPerChromosome-1) // +2 because first and last will be empty to leave room fragments := make([]string, segmentCount+2) for i := 0; i < segmentCount; i++ { start := segmentStart + i*numberOfGenesPerChromosome - fragments[i+1] = parent[start : start+numberOfGenesPerChromosome] + fragments[i+1] = parentGenes[start : start+numberOfGenesPerChromosome] } start := 1 end := segmentCount @@ -250,25 +237,23 @@ func (solver *Solver) shift(strategy strategyInfo, numberOfGenesPerChromosome in start++ } - childGenes := bytes.NewBuffer(make([]byte, 0, len(parent))) + childGenes := bytes.NewBuffer(make([]byte, 0, len(parentGenes))) if segmentStart > 0 { - childGenes.WriteString(parent[0:segmentStart]) + childGenes.WriteString(parentGenes[0:segmentStart]) } for i := start; i <= end; i++ { childGenes.WriteString(fragments[i]) } - if childGenes.Len() < len(parent) { - childGenes.WriteString(parent[childGenes.Len():len(parent)]) + if childGenes.Len() < len(parentGenes) { + childGenes.WriteString(parentGenes[childGenes.Len():len(parentGenes)]) } - child := sequenceInfo{genes: childGenes.String(), strategy: strategy} - child.fitness = getFitness(child.genes) + child := sequenceInfo{genes: childGenes.String(), strategy: strategy, parent: parent} select { - case strategy.results <- child: - continue + case strategy.results <- &child: case <-solver.quit: solver.quit <- true return @@ -289,13 +274,10 @@ func (solver *Solver) swap(strategy strategyInfo, numberOfGenesPerChromosome int break } - useBestParent := random.Intn(100) == 0 - parent := solver.pool[0].genes - if !useBestParent { - parent = solver.pool[random.Intn(len(solver.pool))].genes - } + parent := <-solver.randomParent + parentGenes := (*parent).genes - if len(parent) == 1 { + if len(parentGenes) == 1 { select { case <-solver.quit: solver.quit <- true @@ -306,38 +288,36 @@ func (solver *Solver) swap(strategy strategyInfo, numberOfGenesPerChromosome int } } - parentIndexA := random.Intn(len(parent)) - parentIndexB := random.Intn(len(parent)) + parentIndexA := random.Intn(len(parentGenes)) + parentIndexB := random.Intn(len(parentGenes)) - for tries := 0; parentIndexA == parentIndexB && tries < 10; parentIndexB = random.Intn(len(parent)) { + for tries := 0; parentIndexA == parentIndexB && tries < 10; parentIndexB = random.Intn(len(parentGenes)) { tries++ } parentIndexA, parentIndexB = sort(parentIndexA, parentIndexB) - childGenes := bytes.NewBuffer(make([]byte, 0, len(parent))) + childGenes := bytes.NewBuffer(make([]byte, 0, len(parentGenes))) if parentIndexA > 0 { - childGenes.WriteString(parent[:parentIndexA]) + childGenes.WriteString(parentGenes[:parentIndexA]) } - childGenes.WriteString(parent[parentIndexB : parentIndexB+1]) + childGenes.WriteString(parentGenes[parentIndexB : parentIndexB+1]) if parentIndexB-parentIndexA > 1 { - childGenes.WriteString(parent[parentIndexA+1 : parentIndexB]) + childGenes.WriteString(parentGenes[parentIndexA+1 : parentIndexB]) } - childGenes.WriteString(parent[parentIndexA : parentIndexA+1]) + childGenes.WriteString(parentGenes[parentIndexA : parentIndexA+1]) - if parentIndexB+1 < len(parent) { - childGenes.WriteString(parent[parentIndexB+1:]) + if parentIndexB+1 < len(parentGenes) { + childGenes.WriteString(parentGenes[parentIndexB+1:]) } - child := sequenceInfo{genes: childGenes.String(), strategy: strategy} - child.fitness = getFitness(child.genes) + child := sequenceInfo{genes: childGenes.String(), strategy: strategy, parent: parent} select { - case strategy.results <- child: - continue + case strategy.results <- &child: case <-solver.quit: solver.quit <- true return @@ -349,19 +329,19 @@ func (solver *Solver) initializeStrategies(numberOfGenesPerChromosome int, getFi solver.strategies = []strategyInfo{ {name: "crossover ", start: func(strategyIndex int) { solver.crossover(solver.strategies[strategyIndex], numberOfGenesPerChromosome, getFitness) - }, successCount: 0, results: make(chan sequenceInfo, 1)}, + }, successCount: 0, results: make(chan *sequenceInfo, 1)}, {name: "mutate ", start: func(strategyIndex int) { solver.mutate(solver.strategies[strategyIndex], numberOfGenesPerChromosome, getFitness) - }, successCount: 0, results: make(chan sequenceInfo, 1)}, + }, successCount: 0, results: make(chan *sequenceInfo, 1)}, {name: "reverse ", start: func(strategyIndex int) { solver.reverse(solver.strategies[strategyIndex], numberOfGenesPerChromosome, getFitness) - }, successCount: 0, results: make(chan sequenceInfo, 1)}, + }, successCount: 0, results: make(chan *sequenceInfo, 1)}, {name: "shift ", start: func(strategyIndex int) { solver.shift(solver.strategies[strategyIndex], numberOfGenesPerChromosome, getFitness) - }, successCount: 0, results: make(chan sequenceInfo, 1)}, + }, successCount: 0, results: make(chan *sequenceInfo, 1)}, {name: "swap ", start: func(strategyIndex int) { solver.swap(solver.strategies[strategyIndex], numberOfGenesPerChromosome, getFitness) - }, successCount: 0, results: make(chan sequenceInfo, 1)}, + }, successCount: 0, results: make(chan *sequenceInfo, 1)}, } solver.maxStrategySuccess = 1 @@ -372,12 +352,12 @@ func (solver *Solver) initializeStrategies(numberOfGenesPerChromosome int, getFi } func (solver *Solver) inPool(childGenes string) bool { - solver.poolLock.Lock() + solver.distinctPoolLock.Lock() if solver.distinctPool[childGenes] { - solver.poolLock.Unlock() + solver.distinctPoolLock.Unlock() return true } solver.distinctPool[childGenes] = true - solver.poolLock.Unlock() + solver.distinctPoolLock.Unlock() return false } diff --git a/types.go b/types.go index 4044fe3..a6f50b9 100644 --- a/types.go +++ b/types.go @@ -17,30 +17,35 @@ type Solver struct { quit chan bool nextGene, nextChromosome chan string + randomParent chan *sequenceInfo - strategies []strategyInfo - maxStrategySuccess int + strategies []strategyInfo + maxStrategySuccess int + numberOfImprovements int + successParentIsBestParentCount int needNewlineBeforeDisplay bool - maxPoolSize int - pool []sequenceInfo - distinctPool map[string]bool - poolLock sync.Mutex + maxPoolSize int + pool []sequenceInfo + poolLock sync.Mutex + distinctPool map[string]bool + distinctPoolLock sync.Mutex - rand rand.Rand + random rand.Rand } type sequenceInfo struct { genes string fitness int strategy strategyInfo + parent *sequenceInfo } type strategyInfo struct { name string start func(strategyIndex int) successCount int - results chan sequenceInfo + results chan *sequenceInfo index int }