Beispiel #1
0
// Locality test
func testRepr(initFunc func(maxDep int) *node.Node, mutateFunc func(float64, *node.Node), paintFunc func(*node.Node, *imgut.Image)) (avgErr, varErr float64) {
	// Create storage for the images
	indImage := imgut.Create(IMG_W, IMG_H, imgut.MODE_RGB)
	tmpImage := imgut.Create(IMG_W, IMG_H, imgut.MODE_RGB)

	// Build random individuals
	randomIndividuals := make([]*node.Node, N)
	// For each individual
	var totErrorSum float64 = 0
	var totErrorSqr float64 = 0
	for _, i := range randomIndividuals {
		// Initialize it
		i = initFunc(MAX_D)
		// Render it to an image (it will be garbage)
		indImage.Clear()
		paintFunc(i, indImage)
		// Average error for this individual
		var indErrorSum float64 = 0
		var indErrorSqr float64 = 0
		for k := 0; k < M; k++ {
			// Copy the individual
			j := i.Copy()
			// Mutate the individual
			mutateFunc(1, j)
			// Render it to another image
			tmpImage.Clear()
			paintFunc(j, tmpImage)
			// Compute distance
			dist := imgut.PixelRMSE(indImage, tmpImage)
			// Accumulate distance
			indErrorSum += dist
			indErrorSqr += dist * dist
		}
		// Compute average error
		indErrorAvg := indErrorSum / float64(M)
		// Compute variance
		indErrorVar := indErrorSqr/float64(M) - (indErrorAvg * indErrorAvg)
		fmt.Println("  Individual avg error and variance:", indErrorAvg, indErrorVar)

		// Accumulate error
		totErrorSum += indErrorAvg
		totErrorSqr += indErrorAvg * indErrorAvg
	}
	// Compute average error of the averages
	avgErr = totErrorSum / float64(N)
	// Compute variance of the averages
	varErr = totErrorSqr/float64(N) - (avgErr * avgErr)

	fmt.Println("Total error and var:", avgErr, varErr)
	return
}
Beispiel #2
0
func TestRMSE(t *testing.T) {
	rand.Seed(time.Now().UTC().UnixNano())
	// Create a white image
	img1 := imgut.Create(10, 1, imgut.MODE_RGBA)
	img1.FillRect(0, 0, 10, 1, 1.0, 1.0, 1.0)
	// Create a black image
	img2 := imgut.Create(10, 1, imgut.MODE_RGBA)
	img2.FillRect(0, 0, 10, 1, 0.0, 0.0, 0.0)
	//path := "/home/akiross/Dropbox/Dottorato/TeslaPhD/GoGP/rmse_test_image.png"
	//img2.WritePNG(path)

	// Compare RMSEs
	rmseVec := fitnessRMSE(img1, img2)
	rmseImg := fitnessRMSEImage(img1, img2)
	t.Log("Vec RMSE", rmseVec, rmseImg)
}
Beispiel #3
0
func TestPrimitives(t *testing.T) {
	x := MakeIdentityX()
	y := MakeIdentityY()
	c5 := MakeConstant(0.5)
	e := MakeEphimeral("MakeRand", func() *Primitive {
		v := rand.Float64()
		return MakeConstant(NumericOut(v))
	})

	sum := MakeBinary("Sum", func(a, b NumericOut) NumericOut { return a + b })
	sub := MakeBinary("Sub", func(a, b NumericOut) NumericOut { return a - b })
	mul := MakeBinary("Mul", func(a, b NumericOut) NumericOut { return a * b })

	cos := MakeUnary("Cos", func(a NumericOut) NumericOut { return NumericOut(math.Cos(float64(a))) })

	spl := MakeTernary("Spl", func(a, b, c NumericOut) NumericOut {
		if a > 0.5 {
			return b
		} else {
			return c
		}
	})

	sub = sub
	sum = sum
	mul = mul
	cos = cos
	spl = spl
	e, x, y, c5 = e, x, y, c5

	expr := spl.Run(x, y, x)
	t.Log(expr)

	img := imgut.Create(100, 100, imgut.MODE_RGBA)

	// We have to compile the nodes
	exec := expr.Run().(*Primitive)
	// Apply the function
	//	exec(0 0, float64(img.W), float64(img.H), img)
	var call imgut.PixelFunc = func(x, y float64) float64 {
		return float64(exec.Eval(NumericIn(x), NumericIn(y)))
	}
	img.FillMathBounds(call)

	img.WritePNG("test_expr_repr.png")
	t.Fail()
}
Beispiel #4
0
func (ind *Individual) Copy() ga.Individual {
	tmpImg := imgut.Create(ind.set.ImgTarget.W, ind.set.ImgTarget.H, ind.set.ImgTarget.ColorSpace)
	return &Individual{ind.Node.Copy(), ind.fitness, ind.fitIsValid, ind.set, tmpImg}
}
Beispiel #5
0
func (ind *Individual) Initialize() {
	ind.Node = ind.set.GenFunc(ind.set.MaxDepth)
	ind.ImgTemp = imgut.Create(ind.set.ImgTarget.W, ind.set.ImgTarget.H, ind.set.ImgTarget.ColorSpace)
}
Beispiel #6
0
func (c *Configuration) RandomSolution() hc.Solution {
	n := node.MakeTreeHalfAndHalf(c.MaxDepth, c.Functionals, c.Terminals)
	tmpImg := imgut.Create(c.ImgTarget.W, c.ImgTarget.H, c.ImgTarget.ColorSpace)
	return &Solution{n, tmpImg, c}
}
Beispiel #7
0
func (s *Solution) Copy() hc.Solution {
	tmpImg := imgut.Create(s.Conf.ImgTarget.W, s.Conf.ImgTarget.H, s.Conf.ImgTarget.ColorSpace)
	return &Solution{s.Node.Copy(), tmpImg, s.Conf}
}
Beispiel #8
0
func Evolve(calcMaxDepth func(*imgut.Image) int, fun, ter []gp.Primitive, drawfun func(*base.Individual, *imgut.Image)) {
	startTime := time.Now()

	// Setup options
	fs := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	numGen := fs.Int("g", 100, "Number of generations")
	popSize := fs.Int("p", 1000, "Size of population")
	saveInterval := fs.Int("n", 25, "Generations interval between two snapshot saves")
	tournSize := fs.Int("T", 3, "Tournament size")
	pCross := fs.Float64("C", 0.8, "Crossover probability")
	pMut := fs.Float64("M", 0.1, "Bit mutation probability")
	quiet := fs.Bool("q", false, "Quiet mode")
	fElite := fs.Bool("el", false, "Enable elite individual")

	fInitFull := fs.Bool("full", true, "Enable full initialization")
	fInitGrow := fs.Bool("grow", true, "Enable grow initialization")
	fInitRamped := fs.Bool("ramp", true, "Enable ramped initialization")

	fMutSin := fs.Bool("ms", false, "Enable Single Mutation")
	fMutNod := fs.Bool("mn", false, "Enable Node Mutation")
	fMutSub := fs.Bool("mt", false, "Enable Subtree Mutation")
	fMutAre := fs.Bool("ma", false, "Enable Area Mutation")
	fMutLsubt := fs.Bool("mlt", false, "Enable Level-Subtree Mutation")
	fMutLoc := fs.Bool("ml", false, "Enable Local Mutation")

	fSelect := fs.String("sel", "torun", "Pick selection method (tourn, rmad, irmad)")

	fMultiMut := fs.Bool("mM", false, "Enable multiple mutations")
	fFitness := fs.String("fit", "rmse", "Pick fitness function (rmse, mse, rmsed, ssim)")

	//advStats := fs.Bool("stats", false, "Enable advanced statistics")
	//nps := fs.Bool("nps", false, "Disable population snapshot (no-pop-snap)")
	targetPath := fs.String("t", "", "Target image (PNG) path")
	var basedir, basename string
	cpuProfile := fs.String("cpuprofile", "", "Write CPU profile to file")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fs.PrintDefaults()
		fmt.Fprintf(os.Stderr, "  basedir (string) to be used for saving logs and files\n")
		fmt.Fprintf(os.Stderr, "  basename (string) to be used for saving logs and files\n")
	}

	fs.Parse(os.Args[1:])

	// Check if the argument
	args := fs.Args()

	if len(args) != 2 {
		fs.Usage()
		fmt.Fprintf(os.Stderr, "\nBasename/basedir parameter not specified\n")
		return
	} else {
		basedir = args[0]
		basename = args[1]
	}

	sta := stats.Create(basedir, basename)

	// Build settings
	var settings base.Settings
	// Primitives to use
	settings.Functionals = fun
	settings.Terminals = ter
	// Draw function to use
	settings.Draw = drawfun

	settings.Ramped = *fInitRamped
	if settings.Ramped {
		fmt.Println("Using ramped initialization")
	}

	// Pick initialization method based on flags
	var genFuncBit func(minH, maxH int, funcs, terms []gp.Primitive) *node.Node

	if *fInitFull && !*fInitGrow {
		fmt.Println("Using init strategy: full")
		genFuncBit = node.MakeTreeFull // Initialize tree using full
	} else if !*fInitFull && *fInitGrow {
		fmt.Println("Using init strategy: balanced grow")
		genFuncBit = node.MakeTreeGrowBalanced // Initialize using grow
	} else {
		fmt.Println("Using init strategy: half-and-half")
		genFuncBit = node.MakeTreeHalfAndHalf // Initialize using both (half and half)
	}
	settings.GenFunc = func(maxDep int) *node.Node {
		t := genFuncBit(0, maxDep, fun, ter) // /* TODO */ sistemare la minH
		s := settings
		if _, ok := s.IntCounters[tree_init_depth]; !ok {
			s.IntCounters[tree_init_depth] = new(counter.IntCounter)
		}
		s.IntCounters[tree_init_depth].Count(node.Depth(t))
		return t
	}

	// Build statistic map
	settings.Statistics = make(map[string]*sequence.SequenceStats)
	settings.Counters = make(map[string]*counter.BoolCounter)
	settings.IntCounters = make(map[string]*counter.IntCounter)

	// Names of extra statistics
	statsKeys := []string{}
	countersKeys := []string{}
	intCountersKeys := []string{}

	intCountersKeys = append(intCountersKeys, tree_init_depth)

	if *fMutSin {
		countersKeys = append(countersKeys, mut_single_event, mut_single_improv, mut_single_node_leaves)
		intCountersKeys = append(intCountersKeys, mut_single_node_depth, mut_single_node_repld)
	}
	if *fMutNod {
		countersKeys = append(countersKeys, mut_multi_event, mut_multi_improv, mut_multi_node_leaves)
		intCountersKeys = append(intCountersKeys, mut_multi_node_depth, mut_multi_node_repld)
	}
	if *fMutSub {
		countersKeys = append(countersKeys, mut_tree_event, mut_tree_improv, mut_tree_node_leaves)
		intCountersKeys = append(intCountersKeys, mut_tree_node_depth, mut_tree_node_repld)
	}
	if *fMutAre {
		countersKeys = append(countersKeys, mut_area_event, mut_area_improv, mut_area_node_leaves)
		intCountersKeys = append(intCountersKeys, mut_area_node_depth, mut_area_node_repld)
	}
	if *fMutLsubt {
		countersKeys = append(countersKeys, mut_lsubt_event, mut_lsubt_improv, mut_lsubt_improv)
		intCountersKeys = append(intCountersKeys, mut_lsubt_node_depth, mut_lsubt_node_repld)
	}
	if *fMutLoc {
		countersKeys = append(countersKeys, mut_local_event, mut_local_improv)
		//		intCountersKeys = append(intCountersKeys, "mut_local_") TODO
	}
	if *fMultiMut {
		intCountersKeys = append(intCountersKeys, mut_count_multi)
	}

	if *cpuProfile != "" {
		f, err := os.Create(*cpuProfile)
		if err != nil {
			fmt.Println("ERROR", err)
			panic("Cannot create cpuprofile")
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// Load the target
	var err error
	settings.ImgTarget, err = imgut.Load(*targetPath)
	if err != nil {
		fmt.Fprintln(os.Stderr, "ERROR: Cannot load image", *targetPath)
		panic("Cannot load image")
	}
	if !*quiet {
		fmt.Println("Image format RGB?", settings.ImgTarget.ColorSpace == imgut.MODE_RGB, settings.ImgTarget.ColorSpace)
	}

	// Compute the right value of maxDepth
	settings.MaxDepth = calcMaxDepth(settings.ImgTarget)
	if !*quiet {
		fmt.Println("For area of", settings.ImgTarget.W*settings.ImgTarget.H, "pixels, max depth is", settings.MaxDepth)
	}

	// Create temporary surface, of same size and mode
	//settings.ImgTemp = imgut.Create(settings.ImgTarget.W, settings.ImgTarget.H, settings.ImgTarget.ColorSpace)
	// Create temporary surface for the entire population
	pImgCols := int(math.Ceil(math.Sqrt(float64(*popSize))))
	pImgRows := int(math.Ceil(float64(*popSize) / float64(pImgCols)))
	imgTempPop := imgut.Create(pImgCols*settings.ImgTarget.W, pImgRows*settings.ImgTarget.H, settings.ImgTarget.ColorSpace)

	// Define the operators
	settings.CrossOver = makeCrossover(&settings)
	settings.Mutate = makeMultiMutation(&settings, *fMultiMut, *fMutSin, *fMutNod, *fMutSub, *fMutAre, *fMutLsubt, *fMutLoc)

	// Fitness
	if *fFitness == "mse" {
		settings.FitFunc = base.MakeFitMSE(settings.ImgTarget)
	} else if *fFitness == "rmsed" {
		statsKeys = append(statsKeys, "fit-delta-rmse")
		settings.FitFunc = base.MakeFitEdge(settings.ImgTarget, settings.Statistics)
	} else if *fFitness == "ssim" {
		settings.FitFunc = base.MakeFitSSIM(settings.ImgTarget)
	} else {
		statsKeys = append(statsKeys, "fit-delta-rmse")
		settings.FitFunc = base.MakeFitRMSE(settings.ImgTarget)
	}

	// Selection
	ts := *tournSize
	if *fSelect == "rmad" {
		settings.Select = base.MakeSelectRMAD(ts, ts*ts, settings.BetterThan)
	} else if *fSelect == "irmad" {
		settings.Select = base.MakeSelectIRMAD(ts, ts*ts, settings.BetterThan)
	} else {
		settings.Select = base.MakeSelectTourn(ts, settings.BetterThan)
	}

	// Seed rng
	if !*quiet {
		fmt.Println("Number of CPUs", runtime.NumCPU())
		runtime.GOMAXPROCS(runtime.NumCPU())
		fmt.Println("CPUs limits", runtime.GOMAXPROCS(0))
	}

	// Build population
	pop := new(base.Population)
	pop.Set = &settings
	//pop.TournSize = *tournSize
	pop.Initialize(*popSize)

	// Save initial population FIXME it's for debugging
	/*
		for i := range pop.Pop {
			pop.Pop[i].Draw(imgTemp)
			imgTemp.WritePNG(fmt.Sprintf("pop_ind_%v.png", i))
		}
	*/

	// Number of parallel generators to setup
	pipelineSize := 1 // Was 4 FIXME but there are statistics used in parallel and not ready for concurrent access
	// Containers for pipelined operators
	chXo := make([]<-chan ga.PipelineIndividual, pipelineSize)
	chMut := make([]<-chan ga.PipelineIndividual, pipelineSize)

	// Save best individual, for elitism
	var elite ga.Individual = nil

	// Save time before starting
	//genTime := time.Now()

	// Loop until max number of generation is reached
	for g := 0; g < *numGen; g++ {
		// Compute fitness for every individual with no fitness
		fitnessEval := pop.Evaluate()
		fitnessEval = fitnessEval
		//
		//if !*quiet {
		//	fmt.Println("Generation ", g, "fit evals", fitnessEval, time.Since(genTime))
		//	genTime = time.Now()
		//}

		// Compute various statistics
		sta.Observe(pop)

		// Statistics and samples
		if g%*saveInterval == 0 {
			snapName, snapPopName := sta.SaveSnapshot(pop, *quiet, countersKeys, statsKeys, intCountersKeys)
			// Save best individual
			if false {
				pop.BestIndividual().Fitness()
				pop.BestIndividual().(*base.Individual).ImgTemp.WritePNG(snapName)
			}
			// Save best individual code

			//	pop.BestIndividual().(*base.Individual).Draw(settings.ImgTemp)
			//	settings.ImgTemp.WritePNG(snapName)
			// Save pop images
			pop.Draw(imgTempPop, pImgCols, pImgRows)
			imgTempPop.WritePNG(snapPopName)
		}

		// Setup parallel pipeline
		selectionSize := len(pop.Pop) // int(float64(len(pop.Pop))*0.3)) if you want to randomly generate new individuals
		chSel := ga.GenSelect(pop, selectionSize, float32(g)/float32(*numGen), elite)
		for i := 0; i < pipelineSize; i++ {
			chXo[i] = ga.GenCrossover(chSel, *pCross)
			chMut[i] = ga.GenMutate(chXo[i], *pMut)
		}
		var sel []ga.PipelineIndividual = ga.Collector(ga.FanIn(chMut...), selectionSize)

		// Replace old population and compute statistics
		for i := range sel {
			pop.Pop[i] = sel[i].Ind.(*base.Individual)
			sta.ObserveCrossoverFitness(sel[i].CrossoverFitness, sel[i].InitialFitness)
			sta.ObserveMutationFitness(sel[i].MutationFitness, sel[i].CrossoverFitness)
		}

		// When elitism is activated, get best individual
		if *fElite {
			elite = pop.BestIndividual()
		}

		// Build new individuals
		//base.RampedFill(pop, len(sel), len(pop.Pop))
	}
	fitnessEval := pop.Evaluate()
	fitnessEval = fitnessEval
	// Population statistics
	sta.Observe(pop)

	//if !*quiet {
	//	fmt.Println("Generation", *numGen, "fit evals", fitnessEval)
	//	fmt.Println("Best individual", pop.BestIndividual())
	//}

	snapName, snapPopName := sta.SaveSnapshot(pop, *quiet, countersKeys, statsKeys, intCountersKeys)
	// Save best individual
	if false {
		pop.BestIndividual().Fitness()
		pop.BestIndividual().(*base.Individual).ImgTemp.WritePNG(snapName)
	}
	//	pop.BestIndividual().(*base.Individual).Draw(settings.ImgTemp)
	//	settings.ImgTemp.WritePNG(snapName)
	// Save pop images
	pop.Draw(imgTempPop, pImgCols, pImgRows)
	imgTempPop.WritePNG(snapPopName)

	if !*quiet {
		fmt.Println("Best individual:")
		fmt.Println(pop.BestIndividual())
	}

	elapsedTime := time.Since(startTime)
	fmt.Println("Execution took %s", elapsedTime)

	/*
		bestName := fmt.Sprintf("%v/best/%v.png", basedir, basename)
		if !*quiet {
			fmt.Println("Saving best individual in", bestName)
			fmt.Println(pop.BestIndividual())
		}
		pop.BestIndividual().(*base.Individual).Draw(settings.ImgTemp)
		settings.ImgTemp.WritePNG(bestName)
	*/
}