cut-demo/src/Nest/Core/OptimizeMachine.ts

161 lines
4.7 KiB
TypeScript
Raw Normal View History

2020-04-27 16:39:48 +08:00
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<void>;
//启动
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()
{
}
}