public string GetGraphizString(ProductionOrderBom productionOrderBom) { // Demand(CustomerOrder);20;Truck string graphizString; ProductionOrderOperation productionOrderOperation = productionOrderBom.GetProductionOrderOperation(); if (productionOrderOperation != null) { T_ProductionOrderOperation tProductionOrderOperation = productionOrderOperation.GetValue(); graphizString = $"D: ProductionOrderBom;{ToGraphizString(productionOrderBom)}" // + $"bs({tProductionOrderOperation.StartBackward});" + // $"be({tProductionOrderOperation.EndBackward});" + // $"\\nOperationName: {tProductionOrderOperation}" ; } else { throw new MrpRunException("Every productionOrderBom must have exact one operation."); } return(graphizString); }
public Providers GetAllChildStockExchangeProvidersOf(ProductionOrderOperation operation) { Ids productionOrderBomIds = _dbTransactionData.ProductionOrderBomGetAll() .GetProductionOrderBomsBy(operation); Providers providers = new Providers(); foreach (var productionOrderBomId in productionOrderBomIds) { Demand productionOrderBom = _dbTransactionData.ProductionOrderBomGetById(productionOrderBomId); foreach (var stockExchangeProvider in GetAllChildProvidersOf(productionOrderBom)) { if (stockExchangeProvider.GetType() == typeof(StockExchangeProvider)) { providers.Add((StockExchangeProvider)stockExchangeProvider); } else { throw new MrpRunException( "A child of an productionOrderBom can only a StockExchangeProvider."); } } } if (providers.Any() == false) { return(null); } return(providers); }
public void ProductionOrderOperationAdd(ProductionOrderOperation productionOrderOperation) { // this (productionOrderOperation was already added) can happen, // since an operation can be used multiple times for ProductionorderBoms if (_productionOrderOperations.Contains(productionOrderOperation) == false) { _productionOrderOperations.Add(productionOrderOperation); } }
public DueTime GetEarliestPossibleStartTimeOf( ProductionOrderOperation productionOrderOperation) { DueTime maximumOfEarliestStartTimes = null; Providers providers = ZppConfiguration.CacheManager.GetAggregator() .GetAllChildStockExchangeProvidersOf(productionOrderOperation); foreach (var stockExchangeProvider in providers) { DueTime earliestStartTime = productionOrderOperation.GetStartTimeBackward(); if (earliestStartTime.IsGreaterThanOrEqualTo(stockExchangeProvider .GetStartTimeBackward())) { earliestStartTime = stockExchangeProvider.GetStartTimeBackward(); } else { throw new MrpRunException( "A provider of a demand cannot have a later dueTime."); } Demands stockExchangeDemands = ZppConfiguration.CacheManager.GetAggregator() .GetAllChildDemandsOf(stockExchangeProvider); if (stockExchangeDemands.Any() == false) // StockExchangeProvider has no childs (stockExchangeDemands), // take that from stockExchangeProvider { DueTime childDueTime = stockExchangeProvider.GetStartTimeBackward(); if (childDueTime.IsGreaterThan(earliestStartTime)) { earliestStartTime = childDueTime; } } else // StockExchangeProvider has childs (stockExchangeDemands) { foreach (var stockExchangeDemand in stockExchangeDemands) { DueTime stockExchangeDemandDueTime = stockExchangeDemand.GetStartTimeBackward(); if (stockExchangeDemandDueTime.IsGreaterThan(earliestStartTime)) { earliestStartTime = stockExchangeDemandDueTime; } } } if (maximumOfEarliestStartTimes == null || earliestStartTime.IsGreaterThan(maximumOfEarliestStartTimes)) { maximumOfEarliestStartTimes = earliestStartTime; } } return(maximumOfEarliestStartTimes); }
/** * No need to traverse --> graph is ready, just do some modifications: * remove ProductionOrderBoms, replace ProductionOrder by operationGraph, ... */ private DemandToProviderGraph CreateGraph3() { IDbTransactionData dbTransactionData = ZppConfiguration.CacheManager.GetDbTransactionData(); DemandToProviderGraph demandToProviderGraph = new DemandToProviderGraph(); // replace ProductionOrder by operationGraph foreach (var productionOrder in dbTransactionData.ProductionOrderGetAll()) { if (productionOrder.IsReadOnly() == false) { var productionOrderBomNode = new Node(productionOrder); if (demandToProviderGraph.Contains(productionOrderBomNode)) { OperationGraph operationGraph = new OperationGraph((ProductionOrder)productionOrder); INodes leafOfOperationGraph = operationGraph.GetLeafNodes(); demandToProviderGraph.ReplaceNodeByDirectedGraph(productionOrderBomNode, operationGraph); /*// remove all arrows from leaf, since material must be ready to the * // corresponding operation not to first operation * INodes successorsOfLeaf = * demandToProviderGraph.GetSuccessorNodes(leafOfOperationGraph.GetAny()); * foreach (var successor in successorsOfLeaf) * { * demandToProviderGraph.RemoveEdge(leafOfOperationGraph.GetAny(), successor); * }*/// --> somehow not neccessary } } } // connect every ProductionOrderBom successor to its operation foreach (var productionOrderBom in dbTransactionData.ProductionOrderBomGetAll()) { if (productionOrderBom.IsReadOnly() == false) { var productionOrderBomNode = new Node(productionOrderBom); if (demandToProviderGraph.Contains(productionOrderBomNode)) { ProductionOrderOperation productionOrderOperation = ((ProductionOrderBom)productionOrderBom).GetProductionOrderOperation(); INodes successorNodes = demandToProviderGraph.GetSuccessorNodes(productionOrderBom.GetId()); demandToProviderGraph.RemoveNode(productionOrderBomNode.GetId(), false); foreach (var successor in successorNodes) { demandToProviderGraph.AddEdge( new Edge(new Node(productionOrderOperation), successor)); } } } } return(demandToProviderGraph); }
public Demands CreateProductionOrderBomsForArticleBom( M_ArticleBom articleBom, Quantity quantity, ProductionOrder parentProductionOrder) { Demands newProductionOrderBoms = new Demands(); ProductionOrderOperation productionOrderOperation = null; if (articleBom.OperationId == null) { throw new MrpRunException( "Every PrOBom must have an operation. Add an operation to the articleBom."); } // load articleBom.Operation if (articleBom.Operation == null) { articleBom.Operation = _dbMasterDataCache.M_OperationGetById( new Id(articleBom.OperationId.GetValueOrDefault())); } // don't create an productionOrderOperation twice, take existing if (_alreadyCreatedProductionOrderOperations.ContainsKey(articleBom.Operation)) { productionOrderOperation = _alreadyCreatedProductionOrderOperations[articleBom.Operation]; } ProductionOrderBom newProductionOrderBom = ProductionOrderBom.CreateTProductionOrderBom(articleBom, parentProductionOrder, productionOrderOperation, quantity); if (newProductionOrderBom.HasOperation() == false) { throw new MrpRunException( "Every PrOBom must have an operation. Add an operation to the articleBom."); } if (_alreadyCreatedProductionOrderOperations.ContainsKey(articleBom.Operation) == false) { _alreadyCreatedProductionOrderOperations.Add(articleBom.Operation, newProductionOrderBom.GetProductionOrderOperation()); } newProductionOrderBoms.Add(newProductionOrderBom); return(newProductionOrderBoms); }
/** * Bottom-Up-Traversal */ private void ValidatePredecessorOperationsTransitionTimeIsCorrect( IStackSet <ProductionOrderOperation> predecessorOperations, ProductionOrderOperation lastOperation, IDirectedGraph <INode> operationGraph, IStackSet <INode> traversedOperations) { if (predecessorOperations == null) { return; } foreach (var currentPredecessor in predecessorOperations) { if (currentPredecessor.GetType() == typeof(ProductionOrderOperation)) { ProductionOrderOperation currentOperation = currentPredecessor; traversedOperations.Push(new Node(currentPredecessor)); // transition time MUST be before the start of Operation int expectedStartBackwardLowerLimit = lastOperation.GetValue().EndBackward.GetValueOrDefault() + TransitionTimer.GetTransitionTimeFactor() * currentOperation.GetValue().Duration; int actualStartBackward = currentOperation.GetValue().StartBackward .GetValueOrDefault(); Assert.True(actualStartBackward >= expectedStartBackwardLowerLimit, $"The transition time between the operations is not correct: " + $"expectedStartBackward: {expectedStartBackwardLowerLimit}, actualStartBackward {actualStartBackward}"); INodes predecessorNodesRecursive = operationGraph.GetPredecessorNodesRecursive(new Node(currentPredecessor)); if (predecessorNodesRecursive != null) { IStackSet <ProductionOrderOperation> newPredecessorNodes = new StackSet <ProductionOrderOperation>( predecessorNodesRecursive.Select(x => (ProductionOrderOperation)x.GetEntity())); ValidatePredecessorOperationsTransitionTimeIsCorrect(newPredecessorNodes, currentOperation, operationGraph, traversedOperations); } } else { throw new MrpRunException( "ProductionOrderToOperationGraph should only contain productionOrders/operations."); } } }
public ProductionOrderBoms GetAllProductionOrderBomsBy( ProductionOrderOperation productionOrderOperation) { List <T_ProductionOrderBom> productionOrderBoms = _dbTransactionData .ProductionOrderBomGetAll().GetAllAs <T_ProductionOrderBom>().FindAll(x => x.ProductionOrderOperationId.Equals(productionOrderOperation.GetId() .GetValue())); if (productionOrderBoms == null || productionOrderBoms.Any() == false) { throw new MrpRunException( $"How could an productionOrderOperation({productionOrderOperation}) without an T_ProductionOrderBom exists?"); } return(new ProductionOrderBoms(productionOrderBoms)); }
public ProductionOrderBom GetAnyProductionOrderBomByProductionOrderOperation( ProductionOrderOperation productionOrderOperation) { T_ProductionOrderBom productionOrderBom = _dbTransactionData.ProductionOrderBomGetAll() .GetAllAs <T_ProductionOrderBom>().Find(x => x.ProductionOrderOperationId.Equals(productionOrderOperation.GetId() .GetValue())); if (productionOrderBom == null) { throw new MrpRunException( "How could an productionOrderOperation without an T_ProductionOrderBom exists?"); } return(new ProductionOrderBom(productionOrderBom)); }
public Demands GetProductionOrderBomsBy(ProductionOrderOperation operation) { Ids productionOrderBomIds = _dbTransactionData.ProductionOrderBomGetAll() .GetProductionOrderBomsBy(operation); Demands productionOrderBoms = new Demands(); foreach (var productionOrderBomId in productionOrderBomIds) { Demand productionOrderBom = _dbTransactionData.ProductionOrderBomGetById(productionOrderBomId); productionOrderBoms.Add(productionOrderBom); } return(productionOrderBoms); }
private Priority GetPriorityOfProductionOrderOperation(DueTime now, ProductionOrderOperation givenProductionOrderOperation, DueTime minStartNextOfParentProvider) { IAggregator aggregator = ZppConfiguration.CacheManager.GetAggregator(); Dictionary <HierarchyNumber, DueTime> alreadySummedHierarchyNumbers = new Dictionary <HierarchyNumber, DueTime>(); DueTime sumDurationsOfOperations = DueTime.Zero(); // O(1) List <ProductionOrderOperation> productionOrderOperations = aggregator.GetProductionOrderOperationsOfProductionOrder(givenProductionOrderOperation .GetProductionOrderId()); foreach (var productionOrderOperation in productionOrderOperations) { // only later operations, which have a smaller hierarchyNumber, have to be considered if (productionOrderOperation.GetHierarchyNumber() .IsSmallerThan(givenProductionOrderOperation.GetHierarchyNumber())) { continue; } if (alreadySummedHierarchyNumbers.ContainsKey(productionOrderOperation .GetHierarchyNumber())) { DueTime alreadySummedHierarchyNumber = alreadySummedHierarchyNumbers[ productionOrderOperation.GetHierarchyNumber()]; if (productionOrderOperation.GetDuration().ToDueTime() .IsGreaterThan(alreadySummedHierarchyNumber)) { sumDurationsOfOperations.IncrementBy(productionOrderOperation.GetDuration() .ToDueTime().Minus(alreadySummedHierarchyNumber)); } } else { alreadySummedHierarchyNumbers.Add(productionOrderOperation.GetHierarchyNumber(), productionOrderOperation.GetDuration().ToDueTime()); } } return(new Priority(minStartNextOfParentProvider.Minus(now) .Minus(sumDurationsOfOperations).GetValue())); }
public void TestBackwardSchedulingTransitionTimeBetweenOperationsIsCorrect( string testConfigurationFileName) { InitThisTest(testConfigurationFileName); IDbTransactionData dbTransactionData = ZppConfiguration.CacheManager.ReloadTransactionData(); IDirectedGraph <INode> operationGraph = new OperationGraph(new OrderOperationGraph()); IStackSet <INode> innerLeafs = operationGraph.GetLeafNodes().ToStackSet(); IStackSet <INode> traversedNodes = new StackSet <INode>(); foreach (var leaf in innerLeafs) { INodes predecessorNodesRecursive = operationGraph.GetPredecessorNodesRecursive(leaf); IStackSet <ProductionOrderOperation> newPredecessorNodes = new StackSet <ProductionOrderOperation>( predecessorNodesRecursive.Select(x => (ProductionOrderOperation)x.GetEntity())); ProductionOrderOperation lastOperation = (ProductionOrderOperation)leaf.GetEntity(); ValidatePredecessorOperationsTransitionTimeIsCorrect(newPredecessorNodes, lastOperation, operationGraph, traversedNodes); traversedNodes.Push(leaf); } int expectedTraversedOperationCount = new Stack <ProductionOrderOperation>( dbTransactionData.ProductionOrderOperationGetAll()).Count(); int actualTraversedOperationCount = traversedNodes.Count(); Assert.True(actualTraversedOperationCount.Equals(expectedTraversedOperationCount), $"expectedTraversedOperationCount {expectedTraversedOperationCount} " + $"doesn't equal actualTraversedOperationCount {actualTraversedOperationCount}'"); }
public void ScheduleWithGifflerThompsonAsZaepfel(IPriorityRule priorityRule, IDirectedGraph <INode> operationGraph) { Dictionary <Id, List <Resource> > resourcesByResourceCapabilityId = new Dictionary <Id, List <Resource> >(); foreach (var resourceCapability in _dbMasterDataCache.M_ResourceCapabilityGetAll()) { resourcesByResourceCapabilityId.Add(resourceCapability.GetId(), ZppConfiguration.CacheManager.GetAggregator() .GetResourcesByResourceCapabilityId(resourceCapability.GetId())); } // set correct idleStartTimes in resources from operations of last cycle(s) IDbTransactionData dbTransactionData = ZppConfiguration.CacheManager.GetDbTransactionData(); IDbTransactionData dbTransactionDataArchive = ZppConfiguration.CacheManager.GetDbTransactionDataArchive(); // TODO: This is a huge performance impact, consider having an T_Resource with new field IdleStartTime // so the following collection iterations can be skipped (Archive operations can be huge) CorrectIdleStartTimesOfMachines(dbTransactionData.ProductionOrderOperationGetAll(), resourcesByResourceCapabilityId); CorrectIdleStartTimesOfMachines(dbTransactionDataArchive.ProductionOrderOperationGetAll(), resourcesByResourceCapabilityId); /* * S: Menge der aktuell einplanbaren Arbeitsvorgänge * a: Menge der technologisch an erster Stelle eines Fertigungsauftrags stehenden Arbeitsvorgänge * N(o): Menge der technologisch direkt nachfolgenden Arbeitsoperationen von Arbeitsoperation o * M(o): Maschine auf der die Arbeitsoperation o durchgeführt wird * K: Konfliktmenge (die auf einer bestimmten Maschine gleichzeitig einplanbaren Arbeitsvorgänge) * p(o): Bearbeitungszeit von Arbeitsoperation o (=Duration) * t(o): Startzeit der Operation o (=Start) * d(o): Fertigstellungszeitpunkt von Arbeitsoperation o (=End) * d_min: Minimum der Fertigstellungszeitpunkte * o_min: Operation mit minimalem Fertigstellungszeitpunkt * o1: beliebige Operation aus K (o_dach bei Zäpfel) */ IStackSet <ProductionOrderOperation> S = new StackSet <ProductionOrderOperation>(); // Bestimme initiale Menge: S = a S = CreateS(operationGraph); // t(o) = 0 für alle o aus S foreach (var o in S) { int newStart = o.GetStartTimeBackward().GetValue(); o.SetStartTime(newStart); } // while S not empty do while (S != null && S.Any()) { int d_min = Int32.MaxValue; ProductionOrderOperation o_min = null; foreach (var o in S) { // Berechne d(o) = t(o) + p(o) für alle o aus S int newEnd = o.GetStartTime() + o.GetValue().Duration; o.SetEndTime(newEnd); // Bestimme d_min = min{ d(o) | o aus S } if (o.GetEndTime() < d_min) { d_min = o.GetEndTime(); o_min = o; } } // Bilde Konfliktmenge K = { o | o aus S UND M(o) == M(o_min) UND t(o) < d_min } IStackSet <ProductionOrderOperation> K = new StackSet <ProductionOrderOperation>(); foreach (var o in S) { if (o.GetValue().ResourceCapabilityId.Equals(o_min.GetValue().ResourceCapabilityId) && o.GetStartTime() < d_min) { K.Push(o); } } // while K not empty do if (K.Any()) { // Entnehme Operation mit höchster Prio (o1) aus K und plane auf nächster freier Resource ein List <ProductionOrderOperation> allO1 = new List <ProductionOrderOperation>(); foreach (var machine in resourcesByResourceCapabilityId[o_min.GetResourceCapabilityId()] .OrderBy(x => x.GetIdleStartTime().GetValue())) { if (K.Any() == false) { break; } ProductionOrderOperation o1 = null; o1 = priorityRule.GetHighestPriorityOperation(machine.GetIdleStartTime(), K.GetAll()); if (o1 == null) { throw new MrpRunException("This is not possible if K.Any() is true."); } allO1.Add(o1); K.Remove(o1); o1.SetMachine(machine); // correct op's start time if resource's idleTime is later if (machine.GetIdleStartTime().GetValue() > o1.GetStartTime()) { int newStart = machine.GetIdleStartTime().GetValue(); o1.SetStartTime(newStart); int newEnd = o1.GetStartTime() + o1.GetValue().Duration; o1.SetEndTime(newEnd); } // correct op's start time if op's material is later available DueTime dueTimeOfOperationMaterial = o1.GetEarliestPossibleStartTime(); if (dueTimeOfOperationMaterial.GetValue() > o1.GetStartTime()) { int newStart = dueTimeOfOperationMaterial.GetValue(); o1.SetStartTime(newStart); int newEnd = o1.GetStartTime() + o1.GetValue().Duration; o1.SetEndTime(newEnd); } machine.SetIdleStartTime(new DueTime(o1.GetEndTime())); } // t(o) = d(letzte o1 aus allO1) für alle o aus K (ohne alle o1) foreach (var o in K) { o.SetStartTime(allO1[allO1.Count - 1].GetEndTime()); } /*if N(o1) not empty then * S = S vereinigt N(o1) ohne alle o1 */ foreach (var o1 in allO1) { INode o1AsNode = new Node(o1); INodes allPredecessorsRecursive = operationGraph.GetPredecessorNodesRecursive(o1AsNode); if (allPredecessorsRecursive != null) { IStackSet <ProductionOrderOperation> N = new StackSet <ProductionOrderOperation>( allPredecessorsRecursive.Select(x => (ProductionOrderOperation)x.GetEntity())); // t(o) = d(o1) für alle o aus N(o1) foreach (var n in N) { n.SetStartTime(o1.GetEndTime()); } } // prepare for next round operationGraph.RemoveNode(o1AsNode, true); } S = CreateS(operationGraph); } } }
public void ProductionOrderOperationDelete( ProductionOrderOperation productionOrderOperation) { _productionOrderOperations.Remove(productionOrderOperation); }
/// <summary> /// /// </summary> /// <param name="articleBom"></param> /// <param name="parentProductionOrder"></param> /// <param name="dbMasterDataCache"></param> /// <param name="quantity">of production article to produce /// --> is used for childs as: articleBom.Quantity * quantity</param> /// <param name="productionOrderOperation">use already created, null if no one was created before</param> /// <returns></returns> public static ProductionOrderBom CreateTProductionOrderBom(M_ArticleBom articleBom, Provider parentProductionOrder, ProductionOrderOperation productionOrderOperation, Quantity quantity) { T_ProductionOrderBom productionOrderBom = new T_ProductionOrderBom(); if (quantity == null || quantity.GetValue() == null) { throw new MrpRunException("Quantity is not set."); } productionOrderBom.Quantity = articleBom.Quantity * quantity.GetValue().GetValueOrDefault(); productionOrderBom.ProductionOrderParent = (T_ProductionOrder)parentProductionOrder.ToIProvider(); productionOrderBom.ProductionOrderParentId = productionOrderBom.ProductionOrderParent.Id; // bom is toPurchase if articleBom.Operation == null if (productionOrderOperation != null) { productionOrderBom.ProductionOrderOperation = productionOrderOperation.GetValue(); productionOrderBom.ProductionOrderOperationId = productionOrderBom.ProductionOrderOperation.Id; } if (productionOrderOperation == null && articleBom.Operation != null) { productionOrderBom.ProductionOrderOperation = ProductionManager.CreateProductionOrderOperation(articleBom, parentProductionOrder, quantity); productionOrderBom.ProductionOrderOperationId = productionOrderBom.ProductionOrderOperation.Id; } productionOrderBom.ArticleChild = articleBom.ArticleChild; productionOrderBom.ArticleChildId = articleBom.ArticleChildId; return(new ProductionOrderBom(productionOrderBom)); }
public string GetGraphizString(ProductionOrderOperation productionOrderOperation) { return($"Operation;{productionOrderOperation.GetId()};\\n{productionOrderOperation.GetValue().Name};\\n" + $"bs({productionOrderOperation.GetValue().StartBackward});" + $"be({productionOrderOperation.GetValue().EndBackward});"); }
public Ids GetProductionOrderBomsBy(ProductionOrderOperation operation) { return(_operationToBom[operation.GetId()]); }