コード例 #1
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestNeuronAddOutlinkNonRecurrent(t *testing.T) {

	ng.SeedRandom()

	madeNonRecurrentLink := false
	madeRecurrentLink := false

	for i := 0; i < 100; i++ {
		xnorCortex := BasicCortex()
		neuron := xnorCortex.NeuronUUIDMap()["hidden-neuron1"]
		ok, mutateResult := NeuronAddOutlinkNonRecurrent(neuron)
		if !ok {
			continue
		}
		outboundConnection := mutateResult.(*ng.OutboundConnection)
		if neuron.IsConnectionRecurrent(outboundConnection) {
			madeRecurrentLink = true
		} else {
			madeNonRecurrentLink = true
		}

	}

	assert.True(t, madeNonRecurrentLink)
	assert.False(t, madeRecurrentLink)

}
コード例 #2
0
ファイル: run_examples.go プロジェクト: maxxk/neurvolve
func init() {
	logg.LogKeys["MAIN"] = true
	logg.LogKeys["DEBUG"] = false
	logg.LogKeys["NEURVOLVE"] = true
	logg.LogKeys["NODE_STATE"] = false
	ng.SeedRandom()
}
コード例 #3
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestNeuronAddOutlinkRecurrent(t *testing.T) {

	ng.SeedRandom()

	madeNonRecurrentLink := false
	madeRecurrentLink := false

	for i := 0; i < 100; i++ {
		xnorCortex := BasicCortex()

		neuron := xnorCortex.NeuronUUIDMap()["hidden-neuron1"]

		numOutlinksBefore := len(neuron.Outbound)

		ok, mutateResult := NeuronAddOutlinkRecurrent(neuron)
		if !ok {
			continue
		}
		outboundConnection := mutateResult.(*ng.OutboundConnection)

		numOutlinksAfter := len(neuron.Outbound)

		assert.Equals(t, numOutlinksBefore+1, numOutlinksAfter)

		if neuron.IsConnectionRecurrent(outboundConnection) {

			// the first time we make a nonRecurrentInlink,
			// test the network out
			if madeRecurrentLink == false {
				// make sure the network actually works
				examples := ng.XnorTrainingSamples()
				fitness := xnorCortex.Fitness(examples)
				assert.True(t, fitness >= 0)

			}

			madeRecurrentLink = true
		} else {

			// the first time we make a nonRecurrentInlink,
			// test the network out
			if madeNonRecurrentLink == false {
				// make sure the network doesn't totally break
				examples := ng.XnorTrainingSamples()
				fitness := xnorCortex.Fitness(examples)
				assert.True(t, fitness >= 0)
			}

			madeNonRecurrentLink = true

		}

	}

	assert.True(t, madeNonRecurrentLink)
	assert.True(t, madeRecurrentLink)

}
コード例 #4
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestNeuronMutateActivation(t *testing.T) {

	ng.SeedRandom()
	neuron := &ng.Neuron{
		ActivationFunction: ng.EncodableSigmoid(),
		NodeId:             ng.NewNeuronId("neuron", 0.25),
		Bias:               10,
	}
	NeuronMutateActivation(neuron)
	assert.True(t, neuron.ActivationFunction != nil)
	assert.True(t, neuron.ActivationFunction.Name != ng.EncodableSigmoid().Name)

}
コード例 #5
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestOutspliceNonRecurrent(t *testing.T) {

	ng.SeedRandom()

	numOutspliced := 0
	numIterations := 100

	for i := 0; i < numIterations; i++ {

		cortex := BasicCortex()
		numNeuronsBefore := len(cortex.Neurons)
		neuronLayerMapBefore := cortex.NeuronLayerMap()
		ok, mutateResult := OutspliceNonRecurrent(cortex)
		neuron := mutateResult.(*ng.Neuron)

		if !ok {
			continue
		} else {
			numOutspliced += 1
		}

		assert.True(t, neuron.ActivationFunction != nil)
		numNeuronsAfter := len(cortex.Neurons)
		assert.Equals(t, numNeuronsAfter, numNeuronsBefore+1)

		// should have 1 outbound and inbound
		assert.Equals(t, len(neuron.Inbound), 1)
		assert.Equals(t, len(neuron.Outbound), 1)

		// should be no recurrent connections
		assert.Equals(t, len(neuron.RecurrentInboundConnections()), 0)
		assert.Equals(t, len(neuron.RecurrentOutboundConnections()), 0)

		// should have one more layer (this makes an assumption
		// about the BasicCortex architecture)
		numLayersBefore := len(neuronLayerMapBefore)
		numLayersAfter := len(cortex.NeuronLayerMap())
		assert.Equals(t, numLayersAfter, numLayersBefore+1)

		// run network make sure it runs
		examples := ng.XnorTrainingSamples()
		fitness := cortex.Fitness(examples)
		assert.True(t, fitness >= 0)

	}

	assert.True(t, numOutspliced > 0)

}
コード例 #6
0
func RunTopologyMutatingTrainer() bool {

	ng.SeedRandom()

	// training set
	examples := ng.XnorTrainingSamples()

	// create netwwork with topology capable of solving XNOR
	cortex := ng.BasicCortex()

	// verify it can not yet solve the training set (since training would be useless in that case)
	verified := cortex.Verify(examples)
	if verified {
		panic("neural net already trained, nothing to do")
	}

	shc := &nv.StochasticHillClimber{
		FitnessThreshold:           ng.FITNESS_THRESHOLD,
		MaxIterationsBeforeRestart: 20000,
		MaxAttempts:                10,
		WeightSaturationRange:      []float64{-10000, 10000},
	}

	tmt := &nv.TopologyMutatingTrainer{
		MaxAttempts:                100,
		MaxIterationsBeforeRestart: 5,
		StochasticHillClimber:      shc,
	}
	cortexTrained, succeeded := tmt.TrainExamples(cortex, examples)
	if succeeded {
		logg.LogTo("MAIN", "Successfully trained net: %v", ng.JsonString(cortexTrained))

		// verify it can now solve the training set
		verified = cortexTrained.Verify(examples)
		if !verified {
			logg.LogTo("MAIN", "Failed to verify neural net")
			succeeded = false
		}

	}

	if !succeeded {
		logg.LogTo("MAIN", "Failed to train neural net")
	}

	return succeeded

}
コード例 #7
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestAddNeuronNonRecurrent(t *testing.T) {

	ng.SeedRandom()

	numUnableToAdd := 0
	numIterations := 100

	for i := 0; i < numIterations; i++ {

		cortex := BasicCortex()
		numNeuronsBefore := len(cortex.Neurons)
		ok, mutateResult := AddNeuronNonRecurrent(cortex)

		if !ok {
			numUnableToAdd += 1
			continue
		}

		neuron := mutateResult.(*ng.Neuron)
		assert.True(t, neuron.ActivationFunction != nil)
		numNeuronsAfter := len(cortex.Neurons)
		addedNeuron := numNeuronsAfter == numNeuronsBefore+1
		assert.True(t, addedNeuron)
		if !addedNeuron {
			break
		}

		// should have 1 outbound and inbound
		assert.Equals(t, len(neuron.Inbound), 1)
		assert.Equals(t, len(neuron.Outbound), 1)

		// should be no recurrent connections
		assert.Equals(t, len(neuron.RecurrentInboundConnections()), 0)
		assert.Equals(t, len(neuron.RecurrentOutboundConnections()), 0)

		// run network make sure it runs
		examples := ng.XnorTrainingSamples()
		fitness := cortex.Fitness(examples)
		assert.True(t, fitness >= 0)

	}

	assert.True(t, numUnableToAdd <= (numIterations/3))

}
コード例 #8
0
func DisabledTestUnmarshalCortexFitness(t *testing.T) {

	ng.SeedRandom()

	logg.LogKeys["DEBUG"] = true
	logg.LogKeys["NEURGO"] = true

	// this test is disabled by default since it can take a long time

	// this was a real net that was evolved by the topological mutator
	// before it went through the memetic step.
	// jsonString := `{"NodeId":{"UUID":"cortex","NodeType":"CORTEX","LayerIndex":0},"Sensors":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"VectorLength":2,"Outbound":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25}},{"NodeId":{"UUID":"todo=394057419","NodeType":"NEURON","LayerIndex":0.25}}]}],"Neurons":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25},"Bias":0,"Inbound":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"Weights":[20,20]}],"Outbound":[{"NodeId":{"UUID":"todo=3342881449","NodeType":"NEURON","LayerIndex":0.375}}],"ActivationFunction":{"Name":"sigmoid"}},{"NodeId":{"UUID":"todo=3342881449","NodeType":"NEURON","LayerIndex":0.375},"Bias":-0.36421027459743627,"Inbound":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25},"Weights":[1.8610633947514623]},{"NodeId":{"UUID":"todo=394057419","NodeType":"NEURON","LayerIndex":0.25},"Weights":[0.45355591271633067]}],"Outbound":[{"NodeId":{"UUID":"actuator","NodeType":"ACTUATOR","LayerIndex":0.5}}],"ActivationFunction":{"Name":"sigmoid"}},{"NodeId":{"UUID":"todo=394057419","NodeType":"NEURON","LayerIndex":0.25},"Bias":0.4665982575854781,"Inbound":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"Weights":[0.6618610678776169,3.065256532332561]}],"Outbound":[{"NodeId":{"UUID":"todo=3342881449","NodeType":"NEURON","LayerIndex":0.375}}],"ActivationFunction":{"Name":"tanh"}}],"Actuators":[{"NodeId":{"UUID":"actuator","NodeType":"ACTUATOR","LayerIndex":0.5},"VectorLength":1,"Inbound":[{"NodeId":{"UUID":"todo=3342881449","NodeType":"NEURON","LayerIndex":0.375},"Weights":null}]}]}`

	jsonString2 := `{"NodeId":{"UUID":"cortex","NodeType":"CORTEX","LayerIndex":0},"Sensors":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"VectorLength":2,"Outbound":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25}},{"NodeId":{"UUID":"todo=8550407276","NodeType":"NEURON","LayerIndex":0.25}}]}],"Neurons":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25},"Bias":0,"Inbound":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"Weights":[20,20]}],"Outbound":[{"NodeId":{"UUID":"todo=6014372025","NodeType":"NEURON","LayerIndex":0.375}}],"ActivationFunction":{"Name":"sigmoid"}},{"NodeId":{"UUID":"todo=6014372025","NodeType":"NEURON","LayerIndex":0.375},"Bias":1.216286900747618,"Inbound":[{"NodeId":{"UUID":"neuron","NodeType":"NEURON","LayerIndex":0.25},"Weights":[1.767095335462158]},{"NodeId":{"UUID":"todo=8550407276","NodeType":"NEURON","LayerIndex":0.25},"Weights":[1.0905530851150242]}],"Outbound":[{"NodeId":{"UUID":"actuator","NodeType":"ACTUATOR","LayerIndex":0.5}}],"ActivationFunction":{"Name":"sigmoid"}},{"NodeId":{"UUID":"todo=8550407276","NodeType":"NEURON","LayerIndex":0.25},"Bias":-0.23064534306604623,"Inbound":[{"NodeId":{"UUID":"sensor","NodeType":"SENSOR","LayerIndex":0},"Weights":[-2.069786342256813,-2.0791073119872916]}],"Outbound":[{"NodeId":{"UUID":"todo=6014372025","NodeType":"NEURON","LayerIndex":0.375}}],"ActivationFunction":{"Name":"sigmoid"}}],"Actuators":[{"NodeId":{"UUID":"actuator","NodeType":"ACTUATOR","LayerIndex":0.5},"VectorLength":1,"Inbound":[{"NodeId":{"UUID":"todo=6014372025","NodeType":"NEURON","LayerIndex":0.375},"Weights":null}]}]}`

	jsonBytes := []byte(jsonString2)

	cortex := &ng.Cortex{}
	err := json.Unmarshal(jsonBytes, cortex)
	if err != nil {
		log.Fatal(err)
	}
	assert.True(t, err == nil)

	shc := &StochasticHillClimber{
		FitnessThreshold:           ng.FITNESS_THRESHOLD,
		MaxIterationsBeforeRestart: 20000,
		MaxAttempts:                10,
	}
	examples := ng.XnorTrainingSamples()
	cortexTrained, succeeded := shc.TrainExamples(cortex, examples)
	assert.True(t, succeeded)

	// verify it can now solve the training set
	verified := cortexTrained.Verify(examples)
	assert.True(t, verified)

	fitness := cortexTrained.Fitness(examples)
	log.Printf("Final fitness: %v", fitness)

}
コード例 #9
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestAddNeuronRecurrent(t *testing.T) {

	ng.SeedRandom()

	numAdded := 0
	numIterations := 100

	for i := 0; i < numIterations; i++ {

		cortex := BasicCortex()
		numNeuronsBefore := len(cortex.Neurons)
		ok, mutateResult := AddNeuronRecurrent(cortex)
		neuron := mutateResult.(*ng.Neuron)

		if !ok {
			continue
		} else {
			numAdded += 1
		}

		assert.True(t, neuron != nil)
		assert.True(t, neuron.ActivationFunction != nil)
		numNeuronsAfter := len(cortex.Neurons)
		addedNeuron := numNeuronsAfter == numNeuronsBefore+1
		if !addedNeuron {

			logg.LogPanic("AddNeuronRecurrent %v did not add exactly one neuron.  before: %v after: %v", i, numNeuronsBefore, numNeuronsAfter)

		}

		// run network make sure it runs
		examples := ng.XnorTrainingSamples()
		fitness := cortex.Fitness(examples)
		assert.True(t, fitness >= 0)

	}

	assert.True(t, numAdded > 0)

}
コード例 #10
0
func RunStochasticHillClimber() {

	ng.SeedRandom()

	// training set -- todo: examples := ng.XnorTrainingSamples()
	examples := ng.XnorTrainingSamples()

	// create netwwork with topology capable of solving XNOR
	cortex := ng.XnorCortexUntrained()

	// verify it can not yet solve the training set (since training would be useless in that case)
	verified := cortex.Verify(examples)
	if verified {
		panic("neural net already trained, nothing to do")
	}

	shc := &nv.StochasticHillClimber{
		FitnessThreshold:           ng.FITNESS_THRESHOLD,
		MaxIterationsBeforeRestart: 2000,
		MaxAttempts:                2000,
		WeightSaturationRange:      []float64{-100 * math.Pi, 100 * math.Pi},
	}
	cortexTrained, _, succeeded := shc.TrainExamples(cortex, examples)
	if !succeeded {
		panic("could not train neural net")
	}

	// verify it can now solve the training set
	verified = cortexTrained.Verify(examples)
	if !verified {
		panic("could not verify neural net")
	}

	logg.LogTo("DEBUG", "trained cortex: %v", cortexTrained)

	logg.Log("done")

}
コード例 #11
0
func (shc *StochasticHillClimber) Train(cortex *ng.Cortex, scape Scape) (resultNeuralNet *ng.Cortex, fitness float64, succeeded bool) {

	shc.validate()

	numAttempts := 0

	fittestNeuralNet := cortex.Copy()
	resultNeuralNet = cortex

	// Apply NN to problem and save fitness
	fitness = scape.Fitness(fittestNeuralNet)
	logg.LogTo("MAIN", "Initial fitness: %v", fitness)

	if fitness > shc.FitnessThreshold {
		succeeded = true
		return
	}

	for i := 0; ; i++ {

		// Save the genotype
		candidateNeuralNet := fittestNeuralNet.Copy()

		// Perturb synaptic weights and biases
		PerturbParameters(candidateNeuralNet, shc.WeightSaturationRange)

		// Re-Apply NN to problem
		candidateFitness := scape.Fitness(candidateNeuralNet)
		logg.LogTo("DEBUG", "candidate fitness: %v", fitness)

		// If fitness of perturbed NN is higher, discard original NN and keep new
		// If fitness of original is higher, discard perturbed and keep old.

		if candidateFitness > fitness {
			logg.LogTo("MAIN", "i: %v candidateFitness: %v > fitness: %v", i, candidateFitness, fitness)
			i = 0
			fittestNeuralNet = candidateNeuralNet
			resultNeuralNet = candidateNeuralNet.Copy()
			fitness = candidateFitness
		}

		if candidateFitness > shc.FitnessThreshold {
			logg.LogTo("MAIN", "candidateFitness: %v > Threshold.  Success at i=%v", candidateFitness, i)
			succeeded = true
			break
		}

		if ng.IntModuloProper(i, shc.MaxIterationsBeforeRestart) {
			logg.LogTo("MAIN", "** restart hill climber.  fitness: %f i/max: %d/%d", fitness, numAttempts, shc.MaxAttempts)
			numAttempts += 1
			i = 0
			shc.resetParametersToRandom(fittestNeuralNet)
			ng.SeedRandom()
		}

		if numAttempts >= shc.MaxAttempts {
			succeeded = false
			break
		}

	}

	return

}
コード例 #12
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestNeuronAddInlinkNonRecurrent(t *testing.T) {

	ng.SeedRandom()

	madeNonRecurrentInlink := false
	madeRecurrentInlink := false
	firstTime := true

	// since it's stochastic, repeat the operation many times and make
	// sure that it always produces expected behavior
	for i := 0; i < 100; i++ {

		xnorCortex := ng.XnorCortex()
		sensor := xnorCortex.Sensors[0]
		neuron := xnorCortex.NeuronUUIDMap()["output-neuron"]
		hiddenNeuron1 := xnorCortex.NeuronUUIDMap()["hidden-neuron1"]
		targetLayerIndex := hiddenNeuron1.NodeId.LayerIndex

		// add a new neuron at the same layer index as the hidden neurons
		hiddenNeuron3 := &ng.Neuron{
			ActivationFunction: ng.EncodableSigmoid(),
			NodeId:             ng.NewNeuronId("hidden-neuron3", targetLayerIndex),
			Bias:               -30,
		}

		hiddenNeuron3.Init()
		xnorCortex.Neurons = append(xnorCortex.Neurons, hiddenNeuron3)
		weights := randomWeights(sensor.VectorLength)
		sensor.ConnectOutbound(hiddenNeuron3)
		hiddenNeuron3.ConnectInboundWeighted(sensor, weights)

		ok, mutateResult := NeuronAddInlinkNonRecurrent(neuron)
		if !ok {
			continue
		}
		inboundConnection := mutateResult.(*ng.InboundConnection)

		if neuron.IsInboundConnectionRecurrent(inboundConnection) {
			madeRecurrentInlink = true
		} else {
			madeNonRecurrentInlink = true
		}

		if firstTime == true {

			// only two possibilities - the hiddenNeuron3 or the
			// sensor.  if it was the sensor, then the hiddenNeuron3
			// is "dangliing" and so lets connect it
			if inboundConnection.NodeId.UUID == "sensor" {
				weights2 := randomWeights(1)
				hiddenNeuron3.ConnectOutbound(neuron)
				neuron.ConnectInboundWeighted(hiddenNeuron3, weights2)
			}

			// run network make sure it runs
			examples := ng.XnorTrainingSamples()
			fitness := xnorCortex.Fitness(examples)
			assert.True(t, fitness >= 0)

			firstTime = false
		}

	}

	assert.True(t, madeNonRecurrentInlink)
	assert.False(t, madeRecurrentInlink)

}
コード例 #13
0
ファイル: mutator_test.go プロジェクト: maxxk/neurvolve
func TestOutspliceRecurrent(t *testing.T) {

	logg.LogKeys["TEST"] = true
	logg.LogKeys["NEURVOLVE"] = true

	ng.SeedRandom()

	numOutspliced := 0
	numOutsplicedWithNewLayer := 0
	numOutsplicedWithExistingLayer := 0
	numIterations := 100

	for i := 0; i < numIterations; i++ {

		cortex := BasicCortexRecurrent()

		// run network make sure it runs
		examplesBefore := ng.XnorTrainingSamples()
		fitnessBefore := cortex.Fitness(examplesBefore)
		assert.True(t, fitnessBefore >= 0)

		// recreate network
		cortex = BasicCortexRecurrent()

		numNeuronsBefore := len(cortex.Neurons)
		neuronLayerMapBefore := cortex.NeuronLayerMap()
		ok, mutateResult := OutspliceRecurrent(cortex)
		neuron := mutateResult.(*ng.Neuron)

		if !ok {
			continue
		} else {
			numOutspliced += 1
		}

		assert.True(t, neuron.ActivationFunction != nil)
		numNeuronsAfter := len(cortex.Neurons)
		assert.Equals(t, numNeuronsAfter, numNeuronsBefore+1)

		// should have 1 outbound and inbound
		assert.Equals(t, len(neuron.Inbound), 1)
		assert.Equals(t, len(neuron.Outbound), 1)

		// increment counter if layer added
		numLayersBefore := len(neuronLayerMapBefore)
		numLayersAfter := len(cortex.NeuronLayerMap())
		if numLayersAfter == numLayersBefore+1 {
			numOutsplicedWithNewLayer += 1
		} else {
			numOutsplicedWithExistingLayer += 1
		}

		// run network make sure it runs
		examples := ng.XnorTrainingSamples()
		fitness := cortex.Fitness(examples)
		assert.True(t, fitness >= 0)

	}

	assert.True(t, numOutspliced > 0)
	assert.True(t, numOutsplicedWithNewLayer > 0)
	assert.True(t, numOutsplicedWithExistingLayer > 0)

}
コード例 #14
0
func (tmt *TopologyMutatingTrainer) Train(cortex *ng.Cortex, scape Scape) (fittestCortex *ng.Cortex, succeeded bool) {

	ng.SeedRandom()

	shc := tmt.StochasticHillClimber

	includeNonTopological := false
	mutators := CortexMutatorsNonRecurrent(includeNonTopological)

	originalCortex := cortex.Copy()

	currentCortex := cortex

	// Apply NN to problem and save fitness
	logg.LogTo("MAIN", "Get initial fitness")
	fitness := scape.Fitness(currentCortex)
	logg.LogTo("MAIN", "Initial fitness: %v", fitness)

	if fitness > shc.FitnessThreshold {
		succeeded = true
		return
	}

	for i := 0; ; i++ {

		logg.LogTo("MAIN", "Before mutate.  i/max: %d/%d", i, tmt.MaxAttempts)

		// before we mutate the cortex, we need to init it,
		// otherwise things like Outsplice will fail because
		// there are no DataChan's.
		currentCortex.Init()

		// mutate the network
		randInt := RandomIntInRange(0, len(mutators))
		mutator := mutators[randInt]
		ok, _ := mutator(currentCortex)
		if !ok {
			logg.LogTo("MAIN", "Mutate didn't work, retrying...")
			continue
		}

		isValid := currentCortex.Validate()
		if !isValid {
			logg.LogPanic("Cortex did not validate")
		}

		filenameJson := fmt.Sprintf("cortex-%v.json", i)
		currentCortex.MarshalJSONToFile(filenameJson)
		filenameSvg := fmt.Sprintf("cortex-%v.svg", i)
		currentCortex.RenderSVGFile(filenameSvg)
		logg.LogTo("MAIN", "Post mutate cortex svg: %v json: %v", filenameSvg, filenameJson)

		logg.LogTo("MAIN", "Run stochastic hill climber..")

		// memetic step: call stochastic hill climber and see if it can solve it
		fittestCortex, _, succeeded = shc.Train(currentCortex, scape)
		logg.LogTo("MAIN", "stochastic hill climber finished.  succeeded: %v", succeeded)

		if succeeded {
			succeeded = true
			break
		}

		if i >= tmt.MaxAttempts {
			succeeded = false
			break
		}

		if ng.IntModuloProper(i, tmt.MaxIterationsBeforeRestart) {
			logg.LogTo("MAIN", "** Restart .  i/max: %d/%d", i, tmt.MaxAttempts)

			currentCortex = originalCortex.Copy()
			isValid := currentCortex.Validate()
			if !isValid {
				currentCortex.Repair() // TODO: remove workaround
				isValid = currentCortex.Validate()
				if !isValid {
					logg.LogPanic("Cortex could not be repaired")
				}
			}

		}

	}

	return

}