public PopulationItem mutate(PopulationItem p) { var clone = new PopulationItem(); clone.placements = p.placements.ToArray().ToList(); clone.Rotation = p.Rotation.Clone() as float[]; for (int i = 0; i < clone.placements.Count(); i++) { var rand = r.NextDouble(); if (rand < 0.01 * Config.mutationRate) { var j = i + 1; if (j < clone.placements.Count) { var temp = clone.placements[i]; clone.placements[i] = clone.placements[j]; clone.placements[j] = temp; } } rand = r.NextDouble(); if (rand < 0.01 * Config.mutationRate) { clone.Rotation[i] = (float)Math.Floor(r.NextDouble() * Config.rotations) * (360f / Config.rotations); } } return(clone); }
// returns a random individual from the population, weighted to the front of the list (lower fitness value is more likely to be selected) public PopulationItem randomWeightedIndividual(PopulationItem exclude = null) { //var pop = this.population.slice(0); var pop = this.population.ToArray(); if (exclude != null && Array.IndexOf(pop, exclude) >= 0) { pop.splice(Array.IndexOf(pop, exclude), 1); } var rand = r.NextDouble(); float lower = 0; var weight = 1 / (float)pop.Length; float upper = weight; for (var i = 0; i < pop.Length; i++) { // if the random number falls between lower and upper bounds, select this individual if (rand > lower && rand < upper) { return(pop[i]); } lower = upper; upper += 2 * weight * ((pop.Length - i) / (float)pop.Length); } return(pop[0]); }
// single point crossover public PopulationItem[] mate(PopulationItem male, PopulationItem female) { var cutpoint = (int)Math.Round(Math.Min(Math.Max(r.NextDouble(), 0.1), 0.9) * (male.placements.Count - 1)); var gene1 = new List <NFP>(male.placements.Take(cutpoint).ToArray()); var rot1 = new List <float>(male.Rotation.Take(cutpoint).ToArray()); var gene2 = new List <NFP>(female.placements.Take(cutpoint).ToArray()); var rot2 = new List <float>(female.Rotation.Take(cutpoint).ToArray()); int i = 0; for (i = 0; i < female.placements.Count; i++) { if (!gene1.Any(z => z.id == female.placements[i].id)) { gene1.Add(female.placements[i]); rot1.Add(female.Rotation[i]); } } for (i = 0; i < male.placements.Count; i++) { if (!gene2.Any(z => z.id == male.placements[i].id)) { gene2.Add(male.placements[i]); rot2.Add(male.Rotation[i]); } } return(new[] { new PopulationItem() { placements = gene1, Rotation = rot1.ToArray() }, new PopulationItem() { placements = gene2, Rotation = rot2.ToArray() } }); }
public void launchWorkers(NestItem[] parts) { background.ResponseAction = ResponseProcessor; if (ga == null) { List <NFP> adam = new List <NFP>(); var id = 0; for (int i = 0; i < parts.Count(); i++) { if (!parts[i].IsSheet) { for (int j = 0; j < parts[i].Quanity; j++) { var poly = cloneTree(parts[i].Polygon); // deep copy poly.id = id; // id is the unique id of all parts that will be nested, including cloned duplicates poly.source = i; // source is the id of each unique part from the main part list adam.Add(poly); id++; } } } adam = adam.OrderByDescending(z => Math.Abs(GeometryUtil.polygonArea(z))).ToList(); /*List<NFP> shuffle = new List<NFP>(); * Random r = new Random(DateTime.Now.Millisecond); * while (adam.Any()) * { * var rr = r.Next(adam.Count); * shuffle.Add(adam[rr]); * adam.RemoveAt(rr); * } * adam = shuffle;*/ /*#region special case * var temp = adam[1]; * adam.RemoveAt(1); * adam.Insert(9, temp); * #endregion*/ ga = new GeneticAlgorithm(adam.ToArray(), Config); } individual = null; // check if current generation is finished var finished = true; for (int i = 0; i < ga.population.Count; i++) { if (ga.population[i].fitness == null) { finished = false; break; } } if (finished) { //console.log('new generation!'); // all individuals have been evaluated, start next generation ga.generation(); } var running = ga.population.Where((p) => { return(p.processing != null); }).Count(); List <NFP> sheets = new List <NFP>(); List <int> sheetids = new List <int>(); List <int> sheetsources = new List <int>(); List <List <NFP> > sheetchildren = new List <List <NFP> >(); var sid = 0; for (int i = 0; i < parts.Count(); i++) { if (parts[i].IsSheet) { var poly = parts[i].Polygon; for (int j = 0; j < parts[i].Quanity; j++) { var cln = cloneTree(poly); cln.id = sid; // id is the unique id of all parts that will be nested, including cloned duplicates cln.source = poly.source; // source is the id of each unique part from the main part list sheets.Add(cln); sheetids.Add(sid); sheetsources.Add(i); sheetchildren.Add(poly.children); sid++; } } } for (int i = 0; i < ga.population.Count; i++) { //if(running < config.threads && !GA.population[i].processing && !GA.population[i].fitness){ // only one background window now... if (running < 1 && ga.population[i].processing == null && ga.population[i].fitness == null) { ga.population[i].processing = true; // hash values on arrays don't make it across ipc, store them in an array and reassemble on the other side.... List <int> ids = new List <int>(); List <int> sources = new List <int>(); List <List <NFP> > children = new List <List <NFP> >(); for (int j = 0; j < ga.population[i].placements.Count; j++) { var id = ga.population[i].placements[j].id; var source = ga.population[i].placements[j].source; var child = ga.population[i].placements[j].children; //ids[j] = id; ids.Add(id); //sources[j] = source; sources.Add(source.Value); //children[j] = child; children.Add(child); } DataInfo data = new DataInfo() { index = i, sheets = sheets, sheetids = sheetids.ToArray(), sheetsources = sheetsources.ToArray(), sheetchildren = sheetchildren, individual = ga.population[i], config = Config, ids = ids.ToArray(), sources = sources.ToArray(), children = children }; background.BackgroundStart(data); //ipcRenderer.send('background-start', { index: i, sheets: sheets, sheetids: sheetids, sheetsources: sheetsources, sheetchildren: sheetchildren, individual: GA.population[i], config: config, ids: ids, sources: sources, children: children}); running++; } } }