30 unsigned short constrainedLoads = 0;
34 && h->isStart() && h->getLoad()->getQuantity() != 0.0)
36 if (++constrainedLoads > 1)
break;
40 bool backuplogconstraints = data.logConstraints;
55 if (h->getLoad()->getQuantity() == 0.0 || h->getQuantity() == 0.0)
62 loadqty = h->getQuantity();
64 h->getLoad()->solve(*
this,&data);
72 if (!first) recheck =
true;
76 data.logConstraints =
false;
82 while (constrainedLoads>1 && opplan->
getDates()!=orig
88 data.logConstraints = backuplogconstraints;
126 if (data.constrainedPlanning && !checkOperationLeadtime(opplan,data,
true))
153 if (isCapacityConstrained())
156 checkOperationCapacity(opplan,data);
167 matnext.
setStart(Date::infinitePast);
168 matnext.
setEnd(Date::infiniteFuture);
173 if (g->getFlow()->isConsumer())
177 if (g->getFlow()->getAlternate())
178 g->setFlow(g->getFlow()->getAlternate());
184 g->getFlow()->solve(*
this,&data);
202 opplan, 0.01, data.
state->
a_date, Date::infinitePast,
false,
false
223 a_qty = - q_qty_Flow / g->getFlow()->getQuantity();
240 opplan, orig_opplan_qty, Date::infinitePast, matnext.
getEnd()
248 <<
" Retrying new date." << endl;
258 opplan, orig_opplan_qty, matnext.
getStart(),
277 <<
" Retrying with a smaller quantity: "
293 if (a_qty <= ROUNDING_ERROR && !data.state->forceLate
295 && matnext.
getStart() != Date::infiniteFuture
296 && matnext.
getStart() != Date::infinitePast
297 && (data.constrainedPlanning && isCapacityConstrained()))
304 <<
" Recheck capacity" << endl;
308 (opplan, orig_opplan_qty,
314 checkOperationCapacity(opplan,data);
340 if (!data.constrainedPlanning || (!isFenceConstrained() && !isLeadtimeConstrained()))
348 if (isFenceConstrained()
355 bool checkSetup =
true;
361 if (extra && isCapacityConstrained())
364 if (j->hasAlternates())
372 if (i != opplan->
end()
437 if (data.logConstraints)
461 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
465 double flow_qty_per = 1.0;
553 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
562 double flow_qty = 1.0;
568 for (Operation::Operationlist::const_iterator
586 oper, a_qty, Date::infinitePast,
601 for (Operation::Operationlist::const_reverse_iterator
611 (*e)->solve(*
this,v);
621 if (delay < data->state->a_date - q_date)
625 data->
state->
a_date, Date::infinitePast,
false,
false
627 if (at.
end > max_Date) max_Date = at.
end;
649 data->
state->
a_date = (max_Date ? max_Date : Date::infiniteFuture);
658 if (!prev_owner_opplan) data->
add(a);
698 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
712 double top_flow_qty_per = 0.0;
713 bool top_flow_exists =
false;
720 top_flow_exists =
true;
725 bool originalPlanningMode = data->constrainedPlanning;
726 data->constrainedPlanning =
true;
729 bool originalLogConstraints = data->logConstraints;
738 bool effectiveOnly =
true;
739 Date a_date = Date::infiniteFuture;
746 bool plannedAlternate =
false;
747 double bestAlternateValue = DBL_MAX;
748 double bestAlternateQuantity = 0;
749 Operation* bestAlternateSelection = NULL;
752 for (Operation::Operationlist::const_iterator altIter
758 bool nextalternate =
true;
765 if (props.first == 0.0
766 || (effectiveOnly && !props.second.within(data->
state->
q_date))
767 || (!effectiveOnly && props.second.getEnd() > data->
state->
q_date)
774 effectiveOnly =
false;
781 ask_date = effectiveOnly ? origQDate : props.second.getEnd();
785 double sub_flow_qty_per = 0.0;
788 Flow* f = (*altIter)->findFlow(buf, ask_date);
791 else if (!top_flow_exists)
796 data->constrainedPlanning = originalPlanningMode;
798 +
"' for buffer '" + buf->
getName() +
"'");
803 sub_flow_qty_per = 1.0;
808 firstAlternate = *altIter;
809 firstFlowPer = sub_flow_qty_per + top_flow_qty_per;
813 if (*altIter != firstAlternate)
815 data->logConstraints =
false;
822 data->logConstraints = originalLogConstraints;
829 oper, a_qty, Date::infinitePast, ask_date,
830 d, prev_owner_opplan,
false
833 if (!prev_owner_opplan) data->
add(a);
840 data->
state->
q_qty = a_qty / (sub_flow_qty_per + top_flow_qty_per);
850 <<
"' tries alternate '" << *altIter <<
"' " << endl;
851 (*altIter)->solve(*
this,v);
856 try {(*altIter)->solve(*
this,v);}
861 data->constrainedPlanning = originalPlanningMode;
862 data->logConstraints = originalLogConstraints;
867 double deltaCost = data->
state->
a_cost - beforeCost;
886 data->
state->
a_qty *= (sub_flow_qty_per + top_flow_qty_per);
897 <<
"' evaluates alternate '" << *altIter <<
"': quantity " << data->
state->
a_qty
898 <<
", cost " << deltaCost <<
", penalty " << deltaPenalty << endl;
908 plannedAlternate =
true;
911 if (data->
state->
a_qty > 0) nextalternate =
false;
932 val = (deltaCost + deltaPenalty) / data->
state->
a_qty;
935 LogicException(
"Unsupported search mode for alternate operation '"
941 && data->
state->
a_qty > bestAlternateQuantity)
945 bestAlternateValue = val;
946 bestAlternateSelection = *altIter;
948 bestFlowPer = sub_flow_qty_per + top_flow_qty_per;
949 bestQDate = ask_date;
962 effectiveOnly =
false;
974 <<
"' chooses alternate '" << bestAlternateSelection <<
"' " << search << endl;
980 oper, a_qty, Date::infinitePast, bestQDate,
981 d, prev_owner_opplan,
false
984 if (!prev_owner_opplan) data->
add(a);
994 bestAlternateSelection->
solve(*
this,v);
1036 if (!originalPlanningMode && fabs(origQqty - a_qty) <
ROUNDING_ERROR && firstAlternate)
1039 data->constrainedPlanning =
false;
1040 data->logConstraints =
false;
1045 <<
"' plans unconstrained on alternate '" << firstAlternate <<
"' " << search << endl;
1051 oper, a_qty, Date::infinitePast, origQDate,
1052 d, prev_owner_opplan,
false
1055 if (!prev_owner_opplan) data->
add(a);
1065 firstAlternate->
solve(*
this,v);
1085 data->constrainedPlanning = originalPlanningMode;
1086 data->logConstraints = originalLogConstraints;