From f67b99082d666639c4ca17a048a63a3acf3f3af5 Mon Sep 17 00:00:00 2001 From: DarioS Date: Wed, 23 Feb 2022 11:29:41 +0100 Subject: [PATCH] DataBeam : - migliorata ottimizzazione travi in barre. --- NestProcess.lua | 148 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 130 insertions(+), 18 deletions(-) diff --git a/NestProcess.lua b/NestProcess.lua index e15266b..7bcb751 100644 --- a/NestProcess.lua +++ b/NestProcess.lua @@ -114,6 +114,22 @@ local function NewMachGroupName() return nMaxMachGroup + 1 end +local function TotRawCount(Raws) + local nTotRaws = 0 + for RawIndex = 1, #Raws do + nTotRaws = nTotRaws + Raws[RawIndex].Count + end + return nTotRaws +end + +local function TotPartLen(Parts) + local nTotPartLen = 0 + for PartIndex = 1, #Parts do + nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt) + end + return nTotPartLen +end + -- Imposto direttorio libreria specializzata per Travi local sBaseDir = EgtGetSourceDir() EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua') @@ -146,7 +162,16 @@ local nErrCnt = 0 local nWarnCnt = 0 -- Grezzi -local Raws = { LenToFill = LEN["1"], StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1, Count = QTY["1"]} +-- lista dei grezzi +local Raws = {} +-- creo tabella dei grezzi +for nIndex, nLen in pairs( LEN) do + table.insert(Raws, {LenToFill = nLen, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1}) +end +for nIndex, nQty in pairs( QTY) do + Raws[tonumber(nIndex)].Count = nQty +end + local nTotRaws = Raws.Count -- Pezzi @@ -156,50 +181,137 @@ local Parts = {} for nPartId, nCount in pairs( PART) do -- recupero lunghezza pezzo local Len = EgtGetInfo( nPartId, "L", 'd') - local DispLen = EgtIf( Len < 1000, 2000, 0) + local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0) table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = nCount}) end +-- lunghezza totale pezzi +local dTotPartLen = TotPartLen( Parts) +-- calcolo media delle barre necessarie +local NeededRawsForType = {} +for RawIndex = 1, #Raws do + NeededRawsForType[RawIndex] = ceil( dTotPartLen / Raws[RawIndex].LenToFill) +end +local RawQtySum = 0 +for NeededRawIndex = 1, #NeededRawsForType do + RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex] +end +local MediumRawQty = ceil( RawQtySum / #NeededRawsForType) +if MediumRawQty > 1 then + MediumRawQty = MediumRawQty - 1 +end +-- recupero pezzi piu' corti di mille +local ShortList = {} +local LongList = {} +for PartIndex = 1, #Parts do + if Parts[PartIndex].Len <= 1000 then + table.insert( ShortList, Parts[PartIndex]) + else + table.insert( LongList, Parts[PartIndex]) + end +end +-- numero di pezzi piccoli per barra +local ShortCount = 0 +for ShortIndex = 1, #ShortList do + ShortCount = ShortCount + ShortList[ShortIndex].Cnt +end +local ShortForRaw = floor( ShortCount / MediumRawQty) +local ExtraShortForRaw = fmod( ShortCount, MediumRawQty) +-- creo lista pezzi corti singoli +local SingleShortList = {} +for ShortIndex = 1, #ShortList do + for ShortCount = 1, ShortList[ShortIndex].Cnt do + table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1}) + end +end +-- li divido per le barre previste +local RawsShortList = {} +local RawIndex = 0 +local ShortRawIndex = 0 +for ShortIndex = 1, #SingleShortList do + if ShortRawIndex > 0 then + table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex]) + ShortRawIndex = ShortRawIndex - 1 + else + table.insert( RawsShortList, {SingleShortList[ShortIndex]}) + RawIndex = RawIndex + 1 + ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1 + end +end + -- Ciclo fino ad esaurimento pezzi o barre local nRawTot = 0 local dTime = 0 -while Raws.Count > 0 and PartsToFill( Parts) > 0 do - -- Eseguo ottimizzazione per una barra e visualizzo il risultato - local Res = ExecMaximumFilling( Raws, Parts) +local nCycle = 1 +while TotRawCount( Raws) > 0 and PartsToFill( Parts) > 0 do + + -- creo lista pezzi con pezzi lunghi e pezzi corti di questo Cycle + local PartsToNest = {} + for PartIndex = 1, #LongList do + table.insert( PartsToNest, LongList[PartIndex]) + end + for CycleIndex = 1, #RawsShortList do + if CycleIndex <= nCycle then + for PartIndex = 1, #RawsShortList[CycleIndex] do + table.insert( PartsToNest, RawsShortList[CycleIndex][PartIndex]) + end + end + end + + -- se non ci sono pezzi da nestare, esco + if PartsToFill( PartsToNest) <= 0 then + break + end + -- Eseguo ottimizzazione per ogni lunghezza di barra + local Results = {} + for RawIndex = 1, #Raws do + Results[RawIndex] = ExecMaximumFilling( Raws[RawIndex], PartsToNest) + end + -- verifico quale e' quella con meno scarto + local nMinWasteRawIndex = GDB_ID.NULL + local dMinWaste = 100000 + for ResultIndex = 1, #Results do + local dWaste = (1 - Results[ResultIndex].FillRatio) * Raws[ResultIndex].LenToFill + if dWaste < dMinWaste then + dMinWaste = dWaste + nMinWasteRawIndex = ResultIndex + end + end -- verifico se ci sono pezzi - if Res.DiffParts > 0 then + if Results[nMinWasteRawIndex].DiffParts > 0 then -- creo gruppo di lavorazione local MachGroupName = NewMachGroupName() nMachGroup = EgtAddMachGroup( MachGroupName) - EgtSetInfo( nMachGroup, "BARLEN", Raws.LenToFill) + EgtSetInfo( nMachGroup, "BARLEN", Raws[nMinWasteRawIndex].LenToFill) EgtSetInfo( nMachGroup, "MATERIAL", NEST.MATERIAL) EgtSetInfo( nMachGroup, "AUTONEST", 1) -- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID) EgtSetInfo( nMachGroup, "PATTID", nMachGroup) -- Disegno i pezzi - local CurrX = Raws.StartGap + local CurrX = Raws[nMinWasteRawIndex].StartGap local nInfoIndex = 1 - for i = 1, Res.DiffParts do - local PartIndex = Res.Data[i].Id - local PartId = Parts[PartIndex].Id - local dLen = Parts[PartIndex].Len - for j = 1, Res.Data[i].Count do + for i = 1, Results[nMinWasteRawIndex].DiffParts do + local PartIndex = Results[nMinWasteRawIndex].Data[i].Id + local PartId = PartsToNest[PartIndex].Id + local dLen = PartsToNest[PartIndex].Len + for j = 1, Results[nMinWasteRawIndex].Data[i].Count do -- creo pezzo copia local nPartDuploId = EgtDuploNew( PartId) EgtSetInfo( nMachGroup, "PART" .. nInfoIndex, nPartDuploId .. "," .. CurrX) - CurrX = CurrX + dLen + Raws.MidGap + CurrX = CurrX + dLen + Raws[nMinWasteRawIndex].MidGap nInfoIndex = nInfoIndex + 1 end end nRawTot = nRawTot + 1 end -- Aggiorno per prossima iterazione - Raws.Count = Raws.Count - 1 - for i = 1, Res.DiffParts do - local PartId = Res.Data[i].Id - Parts[PartId].Cnt = Parts[PartId].Cnt - Res.Data[i].Count + Raws[nMinWasteRawIndex].Count = Raws[nMinWasteRawIndex].Count - 1 + for i = 1, Results[nMinWasteRawIndex].DiffParts do + local PartId = Results[nMinWasteRawIndex].Data[i].Id + PartsToNest[PartId].Cnt = PartsToNest[PartId].Cnt - Results[nMinWasteRawIndex].Data[i].Count end + nCycle = nCycle + 1 end -- creo grezzi per ogni gruppo di lavorazione