import { arrayRemoveIf } from "../../Common/ArrayExt"; import { Sleep } from "../../Common/Sleep"; import { clipperCpp } from "../Common/ClipperCpp"; import { Individual } from "./Individual"; import { NestCache } from "./NestCache"; import { Part } from "./Part"; import { Path } from "./Path"; /** * 优化器 * 配置优化器 * 放入零件 * 按下启动 * 按下暂停 * 清理机台 */ export class OptimizeMachine { //配置 Config: { PopulationCount: number;//种群个数 }; //容器板 Bin: Path; //机台上的零件 Parts: Part[]; private _IsSuspend = false; protected _Individuals: Individual[]; constructor() { this.Config = { PopulationCount: 50 }; } //放入零件 PutParts(parts: Part[]) { if (globalThis.document) parts = parts.slice(); arrayRemoveIf(parts, p => p.RotatedStates.length === 0); this.Parts = parts; } callBack: (i: Individual) => Promise; //启动 async Start() { if (this.Parts.length === 0) return; console.log(this.Parts.length); this._IsSuspend = false; NestCache.Clear(); this.Parts.sort((p1, p2) => p2.State.Contour.Area - p1.State.Contour.Area); this._Individuals = [new Individual(this.Parts, 0.8)]; for (let i = 1; i < this.Config.PopulationCount; i++) { let parts = this.Parts.map(p => p.Clone()); if (i < 3) { for (let i = parts.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [parts[i], parts[j]] = [parts[j], parts[i]]; parts[i].Mutate(); } } this._Individuals.push(new Individual(parts, 0.8)); } //2.执行 await this.Run(); } calcCount = 0; best = Infinity; bestP: Individual; bestCount = 0; private async Run() { console.time("1"); if (this.Parts.length === 0) return; //开始自然选择 while (!this._IsSuspend) //实验停止信号 { let goBack = this.calcCount - this.bestCount > 8000; //1.适应环境(放置零件) for (let i = 0; i < this._Individuals.length; i++) { if (globalThis.document || !clipperCpp.lib) await Sleep(0); let p = this._Individuals[i]; if (this.calcCount < 1000 || this.calcCount % 1000 === 0) p.Evaluate(this.Bin, this.best, true, i % 2); else p.Evaluate(this.Bin, this.best); if (!this.bestP || p.Fitness < this.bestP.Fitness) { this.bestP = p; this.best = p.Fitness; await this.callBack(p); } if (goBack) p.mutationRate = 0.5; } this.calcCount += this._Individuals.length; if (this.calcCount % 100 === 0) { console.timeLog("1", this.bestP.Fitness, this.calcCount, NestCache.count1, NestCache.count2); await Sleep(0); } this._Individuals.sort((i1, i2) => i1.Fitness - i2.Fitness); let bestP = this._Individuals[0]; // //回调最好的 // if (bestP.Fitness < this.best) // { // this.best = bestP.Fitness; // this.bestP = bestP; // // console.timeLog("1", this.best, this.calcCount, NestCache.count1, NestCache.count2); // if (this.callBack) // await this.callBack(bestP); // } //自然选择 this._Individuals.splice(-10);//杀死它 for (let i = 0; i < 4; i++) this._Individuals.push(bestP.Clone()); this._Individuals.push(this.bestP.Clone()); for (let i = 0; i < 3; i++) this._Individuals.push(this._Individuals[1].Clone()); for (let i = 0; i < 2; i++) this._Individuals.push(this._Individuals[2].Clone()); //全部突变 for (let p of this._Individuals) { if (p.Fitness !== undefined) p.Mutate(); } } } //暂停 Suspend() { console.timeEnd("1"); console.log(this.best, this.calcCount, NestCache.count1); this._IsSuspend = true; console.log("暂停"); } //继续 Continue() { this._IsSuspend = false; this.Run(); } //清理机台 Clear() { } }