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))
154 if (isCapacityConstrained())
157 checkOperationCapacity(opplan,data);
164 (opplan, orig_opplan_qty,
168 checkOperationCapacity(opplan,data);
180 matnext.
setStart(Date::infinitePast);
181 matnext.
setEnd(Date::infiniteFuture);
186 if (g->getFlow()->isConsumer())
190 if (g->getFlow()->getAlternate())
191 g->setFlow(g->getFlow()->getAlternate());
197 g->getFlow()->solve(*
this,&data);
215 opplan, 0.01, data.
state->
a_date, Date::infinitePast,
false,
false
236 a_qty = - q_qty_Flow / g->getFlow()->getQuantity();
242 && matnext.
getEnd() <= orig_q_date_max && matnext.
getEnd() > orig_q_date)
253 opplan, orig_opplan_qty, Date::infinitePast, matnext.
getEnd()
261 <<
" Retrying new date." << endl;
271 opplan, orig_opplan_qty, matnext.
getStart(),
290 <<
" Retrying with a smaller quantity: "
306 if (a_qty <= ROUNDING_ERROR && !data.state->forceLate
308 && matnext.
getStart() != Date::infiniteFuture
309 && matnext.
getStart() != Date::infinitePast
310 && (data.constrainedPlanning && isCapacityConstrained()))
317 <<
" Recheck capacity" << endl;
321 (opplan, orig_opplan_qty,
327 checkOperationCapacity(opplan,data);
333 (opplan, orig_opplan_qty,
337 checkOperationCapacity(opplan,data);
364 if (!data.constrainedPlanning || (!isFenceConstrained() && !isLeadtimeConstrained()))
372 if (isFenceConstrained()
379 bool checkSetup =
true;
385 if (extra && isCapacityConstrained())
388 if (j->hasAlternates())
396 if (i != opplan->
end()
461 if (data.logConstraints)
485 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
490 double flow_qty_per = 1.0;
491 double flow_qty_fixed = 0.0;
492 bool fixed_flow =
false;
531 fixed_flow ? flow_qty_fixed : data->
state->
q_qty / flow_qty_per,
541 oper, fixed_flow ? flow_qty_fixed : data->
state->
q_qty / flow_qty_per,
602 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
611 double flow_qty = 1.0;
612 double flow_qty_fixed = 0.0;
613 short fixed_flow = -1;
632 for (Operation::Operationlist::const_iterator
644 throw DataException(
"Can't mix fixed and proportional quantity flows on operation '" + oper->
getName()
652 throw DataException(
"Can't mix fixed and proportional quantity flows on operation '" + oper->
getName()
659 if ((fixed_flow == 0 && flow_qty <= 0.0) || (fixed_flow == 1 && flow_qty_fixed <= 0.0) || (fixed_flow == -1))
666 if (fixed_flow == -1) fixed_flow = 0;
674 oper, a_qty, Date::infinitePast,
692 for (Operation::Operationlist::const_reverse_iterator
702 (*e)->solve(*
this,v);
712 if (delay < data->state->a_date - q_date)
716 data->
state->
a_date, Date::infinitePast,
false,
false
718 if (at.
end > max_Date) max_Date = at.
end;
736 if (a_qty == 0.0 && data->
state->
a_date != Date::infiniteFuture)
740 if (data->
state->
a_date > q_date && delay < data->state->a_date - q_date)
742 if (data->
state->
a_date > max_Date || max_Date == Date::infiniteFuture)
746 data->
state->
a_date = (max_Date ? max_Date : Date::infiniteFuture);
760 if (!prev_owner_opplan) data->
add(a);
777 logger <<
indent(oper->
getLevel()) <<
" Applying lazy delay " << delay <<
" in routing" << endl;
804 if (userexit_operation) userexit_operation.
call(oper,
PythonObject(data->constrainedPlanning));
818 double top_flow_qty_per = 0.0;
819 bool top_flow_exists =
false;
820 bool fixed_flow =
false;
829 top_flow_exists =
true;
834 bool originalPlanningMode = data->constrainedPlanning;
835 data->constrainedPlanning =
true;
838 bool originalLogConstraints = data->logConstraints;
847 bool effectiveOnly =
true;
848 Date a_date = Date::infiniteFuture;
855 bool plannedAlternate =
false;
856 double bestAlternateValue = DBL_MAX;
857 double bestAlternateQuantity = 0;
858 Operation* bestAlternateSelection = NULL;
861 for (Operation::Operationlist::const_iterator altIter
867 bool nextalternate =
true;
874 if (props.first == 0.0
875 || (effectiveOnly && !props.second.within(data->
state->
q_date))
876 || (!effectiveOnly && props.second.getEnd() > data->
state->
q_date)
883 effectiveOnly =
false;
890 ask_date = effectiveOnly ? origQDate : props.second.getEnd();
894 double sub_flow_qty_per = 0.0;
897 Flow* f = (*altIter)->findFlow(buf, ask_date);
900 else if (!top_flow_exists)
905 data->constrainedPlanning = originalPlanningMode;
907 +
"' for buffer '" + buf->
getName() +
"'");
909 else if (f && top_flow_exists)
913 throw DataException(
"Can't mix fixed and proportional quantity flows on operation '" + oper->
getName()
921 sub_flow_qty_per = 1.0;
926 firstAlternate = *altIter;
927 firstFlowPer = sub_flow_qty_per + top_flow_qty_per;
931 if (*altIter != firstAlternate)
933 data->logConstraints =
false;
940 data->logConstraints = originalLogConstraints;
947 oper, a_qty, Date::infinitePast, ask_date,
948 d, prev_owner_opplan,
false
951 if (!prev_owner_opplan) data->
add(a);
961 data->
state->
q_qty = a_qty / (sub_flow_qty_per + top_flow_qty_per);
971 <<
"' tries alternate '" << *altIter <<
"' " << endl;
972 (*altIter)->solve(*
this,v);
977 try {(*altIter)->solve(*
this,v);}
982 data->constrainedPlanning = originalPlanningMode;
983 data->logConstraints = originalLogConstraints;
988 double deltaCost = data->
state->
a_cost - beforeCost;
1008 data->
state->
a_qty = (sub_flow_qty_per + top_flow_qty_per);
1010 data->
state->
a_qty *= (sub_flow_qty_per + top_flow_qty_per);
1019 if (loglevel && search !=
PRIORITY)
1021 <<
"' evaluates alternate '" << *altIter <<
"': quantity " << data->
state->
a_qty
1022 <<
", cost " << deltaCost <<
", penalty " << deltaPenalty << endl;
1032 plannedAlternate =
true;
1035 if (data->
state->
a_qty > 0) nextalternate =
false;
1056 val = (deltaCost + deltaPenalty) / data->
state->
a_qty;
1059 LogicException(
"Unsupported search mode for alternate operation '"
1065 && data->
state->
a_qty > bestAlternateQuantity)
1069 bestAlternateValue = val;
1070 bestAlternateSelection = *altIter;
1072 bestFlowPer = sub_flow_qty_per + top_flow_qty_per;
1073 bestQDate = ask_date;
1086 effectiveOnly =
false;
1098 <<
"' chooses alternate '" << bestAlternateSelection <<
"' " << search << endl;
1104 oper, a_qty, Date::infinitePast, bestQDate,
1105 d, prev_owner_opplan,
false
1108 if (!prev_owner_opplan) data->
add(a);
1121 bestAlternateSelection->
solve(*
this,v);
1166 if (!originalPlanningMode && fabs(origQqty - a_qty) <
ROUNDING_ERROR && firstAlternate)
1169 data->constrainedPlanning =
false;
1170 data->logConstraints =
false;
1175 <<
"' plans unconstrained on alternate '" << firstAlternate <<
"' " << search << endl;
1181 oper, a_qty, Date::infinitePast, origQDate,
1182 d, prev_owner_opplan,
false
1185 if (!prev_owner_opplan) data->
add(a);
1195 firstAlternate->
solve(*
this,v);
1221 data->constrainedPlanning = originalPlanningMode;
1222 data->logConstraints = originalLogConstraints;