00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/tags/0.8.0/include/frepple/solver.h $ 00003 version : $LastChangedRevision: 1185 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2010-02-21 01:00:40 +0100 (Sun, 21 Feb 2010) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007 by Johan De Taeye * 00010 * * 00011 * This library is free software; you can redistribute it and/or modify it * 00012 * under the terms of the GNU Lesser General Public License as published * 00013 * by the Free Software Foundation; either version 2.1 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * 00019 * General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * 00024 * USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 #ifndef SOLVER_H 00029 #define SOLVER_H 00030 00031 #include "frepple/model.h" 00032 #ifndef DOXYGEN 00033 #include <deque> 00034 #include <cmath> 00035 #endif 00036 00037 namespace frepple 00038 { 00039 00040 /** @brief This solver implements a heuristic algorithm for planning demands. 00041 * 00042 * One by one the demands are processed. The demand will consume step by step 00043 * any upstream materials, respecting all constraints on its path.<br> 00044 * The solver supports all planning constraints as defined in Solver 00045 * class.<br> 00046 * See the documentation of the different solve methods to understand the 00047 * functionality in more detail. 00048 * 00049 * The logging levels have the following meaning: 00050 * - 0: Silent operation. Default logging level. 00051 * - 1: Show solver progress for each demand. 00052 * - 2: Show the complete ask&reply communication of the solver. 00053 * - 3: Trace the status of all entities. 00054 */ 00055 class SolverMRP : public Solver 00056 { 00057 protected: 00058 /** This variable stores the constraint which the solver should respect. 00059 * By default no constraints are enabled. */ 00060 short constrts; 00061 00062 /** Behavior of this solver method is: 00063 * - It will ask the consuming flows for the required quantity. 00064 * - The quantity asked for takes into account the quantity_per of the 00065 * producing flow. 00066 * - The date asked for takes into account the post-operation time 00067 * of the operation. 00068 */ 00069 DECLARE_EXPORT void solve(const Operation*, void* = NULL); 00070 00071 /** Behavior of this solver method is: 00072 * - Asks each of the routing steps for the requested quantity, starting 00073 * with the last routing step.<br> 00074 * The time requested for the operation is based on the start date of 00075 * the next routing step. 00076 */ 00077 DECLARE_EXPORT void solve(const OperationRouting*, void* = NULL); 00078 00079 /** Behavior of this solver method is: 00080 * - The solver loops through each alternate operation in order of 00081 * priority. On each alternate operation, the solver will try to plan 00082 * the quantity that hasn't been planned on higher priority alternates. 00083 * - As a special case, operations with zero priority are skipped in the 00084 * loop. These operations are considered to be temporarily unavailable. 00085 * - The requested operation can be planned over multiple alternates. 00086 * We don't garantuee that a request is planned using a single alternate 00087 * operation. 00088 * - The solver properly considers the quantity_per of all flows producing 00089 * into the requested buffer, if such a buffer is specified. 00090 */ 00091 DECLARE_EXPORT void solve(const OperationAlternate*,void* = NULL); 00092 00093 /** Behavior of this solver method: 00094 * - No propagation to upstream buffers at all, even if a producing 00095 * operation has been specified. 00096 * - Always give an answer for the full quantity on the requested date. 00097 */ 00098 DECLARE_EXPORT void solve(const BufferInfinite*,void* = NULL); 00099 00100 /** Behavior of this solver method: 00101 * - Consider 0 as the hard minimum limit. It is not possible 00102 * to plan with a 'hard' safety stock reservation. 00103 * - Minimum inventory is treated as a 'wish' inventory. When replenishing 00104 * a buffer we try to satisfy the minimum target. If that turns out 00105 * not to be possible we use whatever available supply for satisfying 00106 * the demand first. 00107 * - Planning for the minimum target is part of planning a demand. There 00108 * is no planning run independent of demand to satisfy the minimum 00109 * target.<br> 00110 * E.g. If a buffer has no demand on it, the solver won't try to 00111 * replenish to the minimum target.<br> 00112 * E.g. If the minimum target increases after the latest date required 00113 * for satisfying a certain demand that change will not be considered. 00114 * - The solver completely ignores the maximum target. 00115 */ 00116 DECLARE_EXPORT void solve(const Buffer*, void* = NULL); 00117 00118 /** Behavior of this solver method: 00119 * - When the inventory drops below the minimum inventory level, a new 00120 * replenishment is triggered. 00121 * The replenishment brings the inventory to the maximum level again. 00122 * - The minimum and maximum inventory are soft-constraints. The actual 00123 * inventory can go lower than the minimum or exceed the maximum. 00124 * - The minimum, maximum and multiple size of the replenishment are 00125 * hard constraints, and will always be respected. 00126 * - A minimum and maximum interval between replenishment is also 00127 * respected as a hard constraint. 00128 * - No propagation to upstream buffers at all, even if a producing 00129 * operation has been specified. 00130 * - The minimum calendar isn't used by the solver. 00131 * 00132 * @todo Optimize the solver method as follows for the common case of infinite 00133 * buying capability (ie no max quantity + min time): 00134 * - beyond lead time: always reply OK, without rearranging the operation plans 00135 * - at the end of the solver loop, we revisit the procurement buffers to establish 00136 * the final purchasing profile 00137 */ 00138 DECLARE_EXPORT void solve(const BufferProcure*, void* = NULL); 00139 00140 /** Behavior of this solver method: 00141 * - This method simply passes on the request to the referenced buffer. 00142 * It is called from a solve(Operation*) method and passes on the 00143 * control to a solve(Buffer*) method. 00144 * @see checkOperationMaterial 00145 */ 00146 DECLARE_EXPORT void solve(const Flow*, void* = NULL); 00147 00148 /** Behavior of this solver method: 00149 * - The operationplan is checked for a capacity overload. When detected 00150 * it is moved to an earlier date. 00151 * - This move can be repeated until no capacity is found till a suitable 00152 * time slot is found. If the fence and/or leadtime constraints are 00153 * enabled they can restrict the feasible moving time.<br> 00154 * If a feasible timeslot is found, the method exits here. 00155 * - If no suitable time slot can be found at all, the operation plan is 00156 * put on its original date and we now try to move it to a feasible 00157 * later date. Again, successive moves are possible till a suitable 00158 * slot is found or till we reach the end of the horizon. 00159 * The result of the search is returned as the answer-date to the 00160 * solver. 00161 */ 00162 DECLARE_EXPORT void solve(const Resource*, void* = NULL); 00163 00164 /** Behavior of this solver method: 00165 * - Always return OK. 00166 */ 00167 DECLARE_EXPORT void solve(const ResourceInfinite*,void* = NULL); 00168 00169 /** Behavior of this solver method: 00170 * - This method simply passes on the request to the referenced resource. 00171 * With the current model structure it could easily be avoided (and 00172 * thus gain a bit in performance), but we wanted to include it anyway 00173 * to make the solver as generic and future-proof as possible. 00174 * @see checkOperationCapacity 00175 */ 00176 DECLARE_EXPORT void solve(const Load*, void* = NULL); 00177 00178 /** Behavior of this solver method: 00179 * - Respects the following demand planning policies:<br> 00180 * 1) Maximum allowed lateness 00181 * 2) Minimum shipment quantity 00182 * This method is normally called from within the main solve method, but 00183 * it can also be called independently to plan a certain demand. 00184 * @see solve 00185 */ 00186 DECLARE_EXPORT void solve(const Demand*, void* = NULL); 00187 00188 public: 00189 /** This is the main solver method that will appropriately call the other 00190 * solve methods.<br> 00191 * The demands in the model will all be sorted with the criteria defined in 00192 * the demand_comparison() method. For each of demand the solve(Demand*) 00193 * method is called to plan it. 00194 */ 00195 DECLARE_EXPORT void solve(void *v = NULL); 00196 00197 /** Constructor. */ 00198 SolverMRP(const string& n) : Solver(n), constrts(0), maxparallel(0), 00199 plantype(1), lazydelay(86400L), autocommit(true) 00200 {initType(metadata);} 00201 00202 /** Destructor. */ 00203 virtual ~SolverMRP() {} 00204 00205 DECLARE_EXPORT void writeElement(XMLOutput*, const Keyword&, mode=DEFAULT) const; 00206 DECLARE_EXPORT void endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement); 00207 virtual DECLARE_EXPORT PyObject* getattro(const Attribute&); 00208 virtual DECLARE_EXPORT int setattro(const Attribute&, const PythonObject&); 00209 static int initialize(); 00210 00211 virtual const MetaClass& getType() const {return *metadata;} 00212 static DECLARE_EXPORT const MetaClass* metadata; 00213 virtual size_t getSize() const {return sizeof(SolverMRP);} 00214 00215 /** Static constant for the LEADTIME constraint type.<br> 00216 * The numeric value is 1. 00217 * @see MATERIAL 00218 * @see CAPACITY 00219 * @see FENCE 00220 */ 00221 static const short LEADTIME = 1; 00222 00223 /** Static constant for the MATERIAL constraint type.<br> 00224 * The numeric value is 2. 00225 * @see LEADTIME 00226 * @see CAPACITY 00227 * @see FENCE 00228 */ 00229 static const short MATERIAL = 2; 00230 00231 /** Static constant for the CAPACITY constraint type.<br> 00232 * The numeric value is 4. 00233 * @see MATERIAL 00234 * @see LEADTIME 00235 * @see FENCE 00236 */ 00237 static const short CAPACITY = 4; 00238 00239 /** Static constant for the FENCE constraint type.<br> 00240 * The numeric value is 8. 00241 * @see MATERIAL 00242 * @see CAPACITY 00243 * @see LEADTIME 00244 */ 00245 static const short FENCE = 8; 00246 00247 /** Update the constraints to be considered by this solver. This field may 00248 * not be applicable for all solvers. */ 00249 void setConstraints(short i) {constrts = i;} 00250 00251 /** Returns the constraints considered by the solve. */ 00252 short getConstraints() const {return constrts;} 00253 00254 /** Returns true if this solver respects the operation release fences. 00255 * The solver isn't allowed to create any operation plans within the 00256 * release fence. 00257 */ 00258 bool isFenceConstrained() const {return (constrts & FENCE)>0;} 00259 00260 /** Returns true if the solver respects the current time of the plan. 00261 * The solver isn't allowed to create any operation plans in the past. 00262 */ 00263 bool isLeadtimeConstrained() const {return (constrts & LEADTIME)>0;} 00264 00265 /** Returns true if the solver respects the material procurement 00266 * constraints on procurement buffers. 00267 */ 00268 bool isMaterialConstrained() const {return (constrts & MATERIAL)>0;} 00269 00270 /** Returns true if the solver respects capacity constraints. */ 00271 bool isCapacityConstrained() const {return (constrts & CAPACITY)>0;} 00272 00273 /** Returns true if any constraint is relevant for the solver. */ 00274 bool isConstrained() const {return constrts>0;} 00275 00276 /** Returns the plan type: 00277 * - 1: Constrained plan.<br> 00278 * This plan doesn't not violate any constraints.<br> 00279 * In case of material or capacity shortages the demand is delayed 00280 * or planned short. 00281 * - 2: Unconstrained plan with alternate search.<br> 00282 * This unconstrained plan leaves material, capacity and operation 00283 * problems when shortages are found. Availability is searched across 00284 * alternates and the remaining shortage is shown on the primary 00285 * alternate.<br> 00286 * The demand is always fully met on time. 00287 * - 3: Unconstrained plan without alternate search.<br> 00288 * This unconstrained plan leaves material, capacity and operation 00289 * problems when shortages are found. It doesn't evaluate availability 00290 * on alternates.<br> 00291 * The demand is always fully met on time. 00292 */ 00293 short getPlanType() const {return plantype;} 00294 00295 void setPlanType(short b) {plantype = b;} 00296 00297 /** This function defines the order in which the demands are being 00298 * planned.<br> 00299 * The following sorting criteria are appplied in order: 00300 * - demand priority: smaller priorities first 00301 * - demand due date: earlier due dates first 00302 * - demand quantity: smaller quantities first 00303 */ 00304 static DECLARE_EXPORT bool demand_comparison(const Demand*, const Demand*); 00305 00306 /** Update the number of parallel solver threads.<br> 00307 * The default value depends on whether the solver is run in verbose mode 00308 * or not: 00309 * - In normal mode the solver uses as many threads as specified by 00310 * the environment variable NUMBER_OF_PROCESSORS. 00311 * - In verbose mode the solver runs in a single thread to avoid 00312 * mangling the debugging output of different threads. 00313 */ 00314 void setMaxParallel(int i) 00315 { 00316 if (i >= 1) maxparallel = i; 00317 else throw DataException("Invalid number of parallel solver threads"); 00318 } 00319 00320 /** Return the number of threads used for planning. */ 00321 int getMaxParallel() const 00322 { 00323 // Or: Explicitly specified number of threads 00324 if (maxparallel) return maxparallel; 00325 // Or: Default number of threads 00326 else return getLogLevel()>0 ? 1 : Environment::getProcessors(); 00327 } 00328 00329 /** Return the time increment between requests when the answered reply 00330 * date isn't usable. */ 00331 TimePeriod getLazyDelay() const {return lazydelay;} 00332 00333 /** Update the time increment between requests when the answered reply 00334 * date isn't usable. */ 00335 void setLazyDelay(TimePeriod l) 00336 { 00337 if (l > 0L) lazydelay = l; 00338 else throw DataException("Invalid lazy delay"); 00339 } 00340 00341 /** Return whether or not we automatically commit the changes after 00342 * planning a demand. */ 00343 bool getAutocommit() const {return autocommit;} 00344 00345 /** Update whether or not we automatically commit the changes after 00346 * planning a demand. */ 00347 void setAutocommit(const bool b) {autocommit = b;} 00348 00349 /** Specify a Python function that is called before solving a flow. */ 00350 DECLARE_EXPORT void setUserExitFlow(const string& n) {userexit_flow = n;} 00351 00352 /** Specify a Python function that is called before solving a flow. */ 00353 DECLARE_EXPORT void setUserExitFlow(PyObject* p) {userexit_flow = p;} 00354 00355 /** Return the Python function that is called before solving a flow. */ 00356 PythonFunction getUserExitFlow() const {return userexit_flow;} 00357 00358 /** Specify a Python function that is called before solving a demand. */ 00359 DECLARE_EXPORT void setUserExitDemand(const string& n) {userexit_demand = n;} 00360 00361 /** Specify a Python function that is called before solving a demand. */ 00362 DECLARE_EXPORT void setUserExitDemand(PyObject* p) {userexit_demand = p;} 00363 00364 /** Return the Python function that is called before solving a demand. */ 00365 PythonFunction getUserExitDemand() const {return userexit_demand;} 00366 00367 /** Specify a Python function that is called before solving a buffer. */ 00368 DECLARE_EXPORT void setUserExitBuffer(const string& n) {userexit_buffer = n;} 00369 00370 /** Specify a Python function that is called before solving a buffer. */ 00371 DECLARE_EXPORT void setUserExitBuffer(PyObject* p) {userexit_buffer = p;} 00372 00373 /** Return the Python function that is called before solving a buffer. */ 00374 PythonFunction getUserExitBuffer() const {return userexit_buffer;} 00375 00376 /** Specify a Python function that is called before solving a resource. */ 00377 DECLARE_EXPORT void setUserExitResource(const string& n) {userexit_resource = n;} 00378 00379 /** Specify a Python function that is called before solving a resource. */ 00380 DECLARE_EXPORT void setUserExitResource(PyObject* p) {userexit_resource = p;} 00381 00382 /** Return the Python function that is called before solving a resource. */ 00383 PythonFunction getUserExitResource() const {return userexit_resource;} 00384 00385 /** Specify a Python function that is called before solving a operation. */ 00386 DECLARE_EXPORT void setUserExitOperation(const string& n) {userexit_operation = n;} 00387 00388 /** Specify a Python function that is called before solving a operation. */ 00389 DECLARE_EXPORT void setUserExitOperation(PyObject* p) {userexit_operation = p;} 00390 00391 /** Return the Python function that is called before solving a operation. */ 00392 PythonFunction getUserExitOperation() const {return userexit_operation;} 00393 00394 /** Python method for running the solver. */ 00395 static DECLARE_EXPORT PyObject* solve(PyObject*, PyObject*); 00396 00397 /** Python method for commiting the plan changes. */ 00398 static DECLARE_EXPORT PyObject* commit(PyObject*, PyObject*); 00399 00400 /** Python method for undoing the plan changes. */ 00401 static DECLARE_EXPORT PyObject* undo(PyObject*, PyObject*); 00402 00403 private: 00404 typedef map < int, deque<Demand*>, less<int> > classified_demand; 00405 typedef classified_demand::iterator cluster_iterator; 00406 classified_demand demands_per_cluster; 00407 00408 /** Number of parallel solver threads.<br> 00409 * The default value depends on whether the solver is run in verbose mode 00410 * or not: 00411 * - In normal mode the solver uses NUMBER_OF_PROCESSORS threads. 00412 * - In verbose mode the solver runs in a single thread to avoid 00413 * mangling the debugging output of different threads. 00414 */ 00415 int maxparallel; 00416 00417 /** Type of plan to be created. */ 00418 short plantype; 00419 00420 /** Time increments for a lazy replan.<br> 00421 * The solver is expected to return always a next-feasible date when the 00422 * request can't be met. The solver can then retry the request with an 00423 * updated request date. In some corner cases and in case of a bug it is 00424 * possible that no valid date is returned. The solver will then try the 00425 * request with a request date incremented by this value.<br> 00426 * The default value is 1 day. 00427 */ 00428 TimePeriod lazydelay; 00429 00430 /** Enable or disable automatically committing the changes in the plan 00431 * after planning each demand.<br> 00432 * The flag is only respected when planning incremental changes, and 00433 * is ignored when doing a complete replan. 00434 */ 00435 bool autocommit; 00436 00437 /** A Python callback function that is called for each alternate 00438 * flow. If the callback function returns false, that alternate 00439 * flow is an invalid choice. 00440 */ 00441 PythonFunction userexit_flow; 00442 00443 /** A Python callback function that is called for each demand. The return 00444 * value is not used. 00445 */ 00446 PythonFunction userexit_demand; 00447 00448 /** A Python callback function that is called for each buffer. The return 00449 * value is not used. 00450 */ 00451 PythonFunction userexit_buffer; 00452 00453 /** A Python callback function that is called for each resource. The return 00454 * value is not used. 00455 */ 00456 PythonFunction userexit_resource; 00457 00458 /** A Python callback function that is called for each operation. The return 00459 * value is not used. 00460 */ 00461 PythonFunction userexit_operation; 00462 00463 protected: 00464 /** @brief This class is used to store the solver status during the 00465 * ask-reply calls of the solver. 00466 * 00467 */ 00468 struct State 00469 { 00470 /** Points to the demand being planned. */ 00471 Demand* curDemand; 00472 00473 /** Points to the current owner operationplan. This is used when 00474 * operations are nested. */ 00475 OperationPlan* curOwnerOpplan; 00476 00477 /** Points to the current buffer. */ 00478 Buffer* curBuffer; 00479 00480 /** A flag to force the resource solver to move the operationplan to 00481 * a later date where it is feasible.<br> 00482 * Admittedly this is an ugly hack... 00483 */ 00484 bool forceLate; 00485 00486 /** This is the quantity we are asking for. */ 00487 double q_qty; 00488 00489 /** This is the date we are asking for. */ 00490 Date q_date; 00491 00492 /** This is the maximum date we are asking for.<br> 00493 * In case of a post-operation time there is a difference between 00494 * q_date and q_date_max. 00495 */ 00496 Date q_date_max; 00497 00498 /** This is the quantity we can get by the requested Date. */ 00499 double a_qty; 00500 00501 /** This is the Date when we can get extra availability. */ 00502 Date a_date; 00503 00504 /** This is a pointer to a LoadPlan. It is used for communication 00505 * between the Operation-Solver and the Resource-Solver. */ 00506 LoadPlan* q_loadplan; 00507 00508 /** This is a pointer to a FlowPlan. It is used for communication 00509 * between the Operation-Solver and the Buffer-Solver. */ 00510 FlowPlan* q_flowplan; 00511 00512 /** A pointer to an operationplan currently being solved. */ 00513 OperationPlan* q_operationplan; 00514 00515 /** Cost of the reply.<br> 00516 * Only the direct cost should be returned in this field. 00517 */ 00518 double a_cost; 00519 00520 /** Penalty associated with the reply.<br> 00521 * This field contains indirect costs and other penalties that are 00522 * not strictly related to the request. Examples are setup costs, 00523 * inventory carrying costs, ... 00524 */ 00525 double a_penalty; 00526 }; 00527 00528 /** @brief This class is a helper class of the SolverMRP class. 00529 * 00530 * It stores the solver state maintained by each solver thread. 00531 * @see SolverMRP 00532 */ 00533 class SolverMRPdata : public CommandList 00534 { 00535 friend class SolverMRP; 00536 public: 00537 /** Return the solver. */ 00538 SolverMRP* getSolver() const {return sol;} 00539 00540 /** Constructor. */ 00541 SolverMRPdata(SolverMRP* s = NULL, int c = 0, deque<Demand*>* d = NULL) 00542 : sol(s), cluster(c), demands(d), constrainedPlanning(true), 00543 state(statestack), prevstate(statestack-1) {} 00544 00545 /** Verbose mode is inherited from the solver. */ 00546 unsigned short getLogLevel() const {return sol ? sol->getLogLevel() : 0;} 00547 00548 /** This function runs a single planning thread. Such a thread will loop 00549 * through the following steps: 00550 * - Use the method next_cluster() to find another unplanned cluster. 00551 * - Exit the thread if no more cluster is found. 00552 * - Sort all demands in the cluster, using the demand_comparison() 00553 * method. 00554 * - Loop through the sorted list of demands and plan each of them. 00555 * During planning the demands exceptions are caught, and the 00556 * planning loop will simply move on to the next demand. 00557 * In this way, an error in a part of the model doesn't ruin the 00558 * complete plan. 00559 * @see demand_comparison 00560 * @see next_cluster 00561 */ 00562 virtual DECLARE_EXPORT void execute(); 00563 00564 virtual const MetaClass& getType() const {return *SolverMRP::metadata;} 00565 virtual size_t getSize() const {return sizeof(SolverMRPdata);} 00566 00567 bool getVerbose() const 00568 { 00569 throw LogicException("Use the method SolverMRPdata::getLogLevel() instead of SolverMRPdata::getVerbose()"); 00570 } 00571 00572 /** Add a new state to the status stack. */ 00573 inline void push(double q = 0.0, Date d = Date::infiniteFuture) 00574 { 00575 if (state >= statestack + MAXSTATES) 00576 throw RuntimeException("Maximum recursion depth exceeded"); 00577 ++state; 00578 ++prevstate; 00579 state->q_qty = q; 00580 state->q_date = d; 00581 state->curOwnerOpplan = NULL; 00582 state->q_loadplan = NULL; 00583 state->q_flowplan = NULL; 00584 state->q_operationplan = NULL; 00585 state->a_cost = 0.0; 00586 state->a_penalty = 0.0; 00587 } 00588 00589 /** Removes a state from the status stack. */ 00590 inline void pop() 00591 { 00592 if (--state < statestack) 00593 throw LogicException("State stack empty"); 00594 --prevstate; 00595 } 00596 00597 private: 00598 static const int MAXSTATES = 256; 00599 00600 /** Points to the solver. */ 00601 SolverMRP* sol; 00602 00603 /** An identifier of the cluster being replanned. Note that it isn't 00604 * always the complete cluster that is being planned. 00605 */ 00606 int cluster; 00607 00608 /** A deque containing all demands to be (re-)planned. */ 00609 deque<Demand*>* demands; 00610 00611 /** Stack of solver status information. */ 00612 State statestack[MAXSTATES]; 00613 00614 /** True when planning in constrained mode. */ 00615 bool constrainedPlanning; 00616 00617 public: 00618 /** Pointer to the current solver status. */ 00619 State* state; 00620 00621 /** Pointer to the solver status one level higher on the stack. */ 00622 State* prevstate; 00623 }; 00624 00625 /** When autocommit is switched off, this command structure will contain 00626 * all plan changes. 00627 */ 00628 SolverMRPdata commands; 00629 00630 /** This function will check all constraints for an operationplan 00631 * and propagate it upstream. The check does NOT check eventual 00632 * sub operationplans.<br> 00633 * The return value is a flag whether the operationplan is 00634 * acceptable (sometimes in reduced quantity) or not. 00635 */ 00636 DECLARE_EXPORT bool checkOperation(OperationPlan*, SolverMRPdata& data); 00637 00638 /** Verifies whether this operationplan violates the leadtime 00639 * constraints. */ 00640 DECLARE_EXPORT bool checkOperationLeadtime(OperationPlan*, SolverMRPdata&, bool); 00641 00642 /** Verifies whether this operationplan violates the capacity constraint.<br> 00643 * In case it does the operationplan is moved to an earlier or later 00644 * feasible date. 00645 */ 00646 DECLARE_EXPORT void checkOperationCapacity(OperationPlan*, SolverMRPdata&); 00647 }; 00648 00649 00650 /** @brief This class holds functions that used for maintenance of the solver 00651 * code. 00652 */ 00653 class LibrarySolver 00654 { 00655 public: 00656 static void initialize(); 00657 }; 00658 00659 00660 } // end namespace 00661 00662 00663 #endif