solver.h

Go to the documentation of this file.
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

Generated on 21 Mar 2010 for frePPLe by  doxygen 1.6.1