功能:异形优化算法实现优先提前放置功能

pull/2485/head
ChenX 10 months ago
parent ca798cbfc6
commit 83801dc37d

@ -45,6 +45,8 @@ export class Container
StatusKey: string;
IsPrePlace = false;//父零件是提前放置的(程序内部自动设置)
CompartePoint: CompareVectorFn;
constructor(protected BinPath?: Path, private _PlaceType = PlaceType.Box, compare = "xy")
{

@ -1,4 +1,4 @@
import { arrayLast, arrayRemoveOnce } from '../Common/ArrayExt';
import { arrayLast, arrayPushArray, arrayRemoveOnce } from '../Common/ArrayExt';
import { NestFiler } from "../Common/Filer";
import { RandomIndex } from "../Common/Random";
import { Container } from "./Container";
@ -21,7 +21,13 @@ import { PlaceType } from "./PlaceType";
*/
export class Individual
{
constructor(public Parts?: Part[], public mutationRate = 0.5, private bin?: Path, private OddmentsBins: Path[] = [], private ComparePointKeys: string[] = DefaultComparePointKeys) { }
constructor(public Parts?: Part[],
public PreParts?: Part[],
public mutationRate = 0.5,
private bin?: Path,
private OddmentsBins: Path[] = [],
private ComparePointKeys: string[] = DefaultComparePointKeys)
{ }
Fitness: number; //(评估健康) 大板个数-1 + 最后一块板的利用率
Containers: Container[]; //大板列表(已排
@ -41,8 +47,16 @@ export class Individual
this.OddmentsContainers = this.OddmentsBins.map(path => new Container(path, type ?? RandomIndex(3), this.ComparePointKeys[RandomIndex(2)]));
this.InitHoleContainers();
let parts = this.PreParts.concat(this.Parts);
//网洞优先
let parts = this.Parts.filter(p => !this.HoleContainers.some(hole => hole.PutPart(p)));
parts = this.Parts.filter(p => !this.HoleContainers.some(hole =>
{
//如果零件是提前放置的,但是网洞却不是,就先不给他放了(这可能会损失利用率 但是达到了提前放置的需求)
if (p.IsPrePlace && !hole.IsPrePlace)
return false;
hole.PutPart(p);
}));
//之后是余料
parts = parts.filter(p => !this.OddmentsContainers.some(odd => odd.PutPart(p)));
@ -106,7 +120,7 @@ export class Individual
this.Containers = [];
this.HoleContainers = [];
let parts = this.Parts.concat();
let parts = this.PreParts.concat(this.Parts);
while (parts.length > 0)
{
if (this.Containers.length > Math.max(0, bestCount))//提前结束,已经超过最佳用板量
@ -223,6 +237,9 @@ export class Individual
container.ParentId = part.Id;
container.ChildrenIndex = i;
container.ParentM = GNestConfig.RotateHole ? hole.MinPoint : hole.OrigionMinPoint;
container.IsPrePlace = part.IsPrePlace;
this.HoleContainers.push(container);
}
}
@ -230,7 +247,7 @@ export class Individual
Clone()
{
let p = new Individual(this.Parts.map(p => p.Clone()), this.mutationRate, this.bin, this.OddmentsBins, this.ComparePointKeys);
let p = new Individual(this.Parts.map(p => p.Clone()), this.PreParts.map(p => p.Clone()), this.mutationRate, this.bin, this.OddmentsBins, this.ComparePointKeys);
p.Mutate();
return p;
}
@ -242,20 +259,28 @@ export class Individual
* ,,
*/
Mutate()
{
this.MutateParts(this.Parts);
if (this.PreParts.length)
this.MutateParts(this.PreParts);
return this;
}
private MutateParts(parts: Part[])
{
if (this.mutationRate > 0.5)
for (let i = 0; i < this.Parts.length; i++)
for (let i = 0; i < parts.length; i++)
{
let rand = Math.random();
if (rand < this.mutationRate * 0.5)
{
//和下一个调换顺序
let j = i + 1;
if (j < this.Parts.length)
[this.Parts[i], this.Parts[j]] = [this.Parts[j], this.Parts[i]];
if (j < parts.length)
[parts[i], parts[j]] = [parts[j], parts[i]];
}
if (rand < this.mutationRate)
this.Parts[i].Mutate();
parts[i].Mutate();
}
else
{
@ -263,19 +288,18 @@ export class Individual
let rand = Math.random();
if (rand < 0.5)
{
let index = RandomIndex(this.Parts.length - 2);
let count = Math.ceil(RandomIndex(this.Parts.length - 2 - index) * this.mutationRate * 2) || 1;
let parts = this.Parts.splice(index, count);
this.Parts.push(...parts);
this.Parts[index].Mutate();
let index = RandomIndex(parts.length - 2);
let count = Math.ceil(RandomIndex(parts.length - 2 - index) * this.mutationRate * 2) || 1;
arrayPushArray(parts, parts.splice(index, count));
parts[index].Mutate();
}
else
for (let i = 0; i < this.Parts.length; i++)
for (let i = 0; i < parts.length; i++)
{
let rand = Math.random();
if (rand < this.mutationRate)
{
this.Parts[i].Mutate();
parts[i].Mutate();
i += 5;
}
}
@ -299,6 +323,14 @@ export class Individual
[this.Parts[i], this.Parts[j]] = [this.Parts[j], this.Parts[i]];
this.Parts[i].Mutate();
}
if (this.PreParts.length)
for (let i = this.PreParts.length - 1; i > 0; i--)
{
const j = Math.floor(Math.random() * (i + 1));
[this.PreParts[i], this.PreParts[j]] = [this.PreParts[j], this.PreParts[i]];
this.PreParts[i].Mutate();
}
}
//#region -------------------------File-------------------------

@ -14,7 +14,9 @@ export class NestDatabase
Bin: Path; //默认的容器
OddmentsBins: Path[];//余料容器列表
Paths: Path[]; //所有的Path都在这里
Parts: Part[]; //所有的零件
PreParts: Part[];//优先排料的零件
Parts: Part[]; //所有的零件(不再是所有的零件了)
ComparePointKeys: string[] = DefaultComparePointKeys;//用来决定零件靠边模式
//#region -------------------------File-------------------------
@ -32,6 +34,17 @@ export class NestDatabase
}
this.Bin = this.Paths[file.Read()];
PathGeneratorSingle.paths = this.Paths;
count = file.Read();
this.PreParts = [];
for (let i = 0; i < count; i++)
{
let part = new Part();
part.ReadFile(file);
part.IsPrePlace = true;
this.PreParts.push(part);
}
count = file.Read();
this.Parts = [];
for (let i = 0; i < count; i++)
@ -57,12 +70,17 @@ export class NestDatabase
//对象将自身数据写入到文件.
WriteFile(file: NestFiler)
{
file.Write(2);
file.Write(3);
file.Write(this.Paths.length);
for (let path of this.Paths)
path.WriteFile(file);
file.Write(this.Bin.Id);
file.Write(this.PreParts.length);
for (let part of this.Parts)
part.WriteFile(file);
file.Write(this.Parts.length);
for (let part of this.Parts)
part.WriteFile(file);

@ -24,7 +24,10 @@ export class OptimizeMachine
Bin: Path; //默认的容器
OddmentsBins: Path[];//余料容器列表
Parts: Part[]; //所有的零件
PreParts: Part[]; //优先开料的零件
Parts: Part[]; //所有的零件(不再是所有的零件了)
ComparePointKeys: string[] = DefaultComparePointKeys;//用来决定零件靠边模式
// //计算重复的零件 TODO:需要对相同的零件提取出来
@ -64,11 +67,11 @@ export class OptimizeMachine
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, this.Bin, this.OddmentsBins, this.ComparePointKeys)];
this._Individuals = [new Individual(this.Parts, this.PreParts, 0.8, this.Bin, this.OddmentsBins, this.ComparePointKeys)];
for (let i = 1; i < this.Config.PopulationCount; i++)
{
let parts = this.Parts.map(p => p.Clone());
let inv = new Individual(parts, 0.8, this.Bin, this.OddmentsBins, this.ComparePointKeys);
let inv = new Individual(parts, this.PreParts.map(p => p.Clone()), 0.8, this.Bin, this.OddmentsBins, this.ComparePointKeys);
if (i < 5)
inv.BigMutate();
this._Individuals.push(inv);

@ -52,6 +52,8 @@ export class Part<T = any, Matrix = any>
PlaceIndex: number;//放置的大板索引
//#endregion
IsPrePlace = false;//需要优先放置(这个值由程序内部设置)
GroupMap: { [key: number]: Part[]; } = {};
get State(): PartState //零件当前的状态
{

Loading…
Cancel
Save