00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/modules/forecast/module.cpp $ 00003 version : $LastChangedRevision: 955 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2009-05-03 10:36:18 +0200 (Sun, 03 May 2009) $ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * 00024 * * 00025 ***************************************************************************/ 00026 00027 #include "forecast.h" 00028 00029 namespace module_forecast 00030 { 00031 00032 const MetaClass *Forecast::metadata; 00033 const MetaClass *ForecastBucket::metadata; 00034 const MetaClass *ForecastSolver::metadata; 00035 00036 00037 Forecast::MapOfForecasts Forecast::ForecastDictionary; 00038 bool Forecast::Customer_Then_Item_Hierarchy = true; 00039 bool Forecast::Match_Using_Delivery_Operation = true; 00040 TimePeriod Forecast::Net_Late(0L); 00041 TimePeriod Forecast::Net_Early(0L); 00042 unsigned long Forecast::Forecast_Iterations(15L); 00043 double Forecast::Forecast_MadAlfa(0.95); 00044 unsigned long Forecast::Forecast_Skip(5); 00045 00046 00047 MODULE_EXPORT const char* initialize(const CommandLoadLibrary::ParameterList& z) 00048 { 00049 // Initialize only once 00050 static bool init = false; 00051 static const char* name = "forecast"; 00052 if (init) 00053 { 00054 logger << "Warning: Initializing module forecast more than once." << endl; 00055 return name; 00056 } 00057 init = true; 00058 00059 // Process the module parameters 00060 for (CommandLoadLibrary::ParameterList::const_iterator x = z.begin(); 00061 x != z.end(); ++x) 00062 try 00063 { 00064 // Netting 00065 if (x->first == "Net_CustomerThenItemHierarchy") 00066 Forecast::setCustomerThenItemHierarchy(x->second.getBool()); 00067 else if (x->first == "Net_MatchUsingDeliveryOperation") 00068 Forecast::setMatchUsingDeliveryOperation(x->second.getBool()); 00069 else if (x->first == "Net_NetEarly") 00070 Forecast::setNetEarly(x->second.getTimeperiod()); 00071 else if (x->first == "Net_NetLate") 00072 Forecast::setNetLate(x->second.getTimeperiod()); 00073 // Forecasting 00074 else if (x->first == "Forecast_Iterations") 00075 Forecast::setForecastIterations(x->second.getUnsignedLong()); 00076 else if (x->first == "Forecast_madAlfa") 00077 Forecast::setForecastMadAlfa(x->second.getDouble()); 00078 else if (x->first == "Forecast_Skip") 00079 Forecast::setForecastSkip(x->second.getUnsignedLong()); 00080 // Moving average forecast method 00081 else if (x->first == "MovingAverage_buckets") 00082 Forecast::MovingAverage::setDefaultBuckets(x->second.getUnsignedLong()); 00083 // Single exponential forecast method 00084 else if (x->first == "Forecast_SingleExponential_initialAlfa") 00085 Forecast::SingleExponential::setInitialAlfa(x->second.getDouble()); 00086 else if (x->first == "Forecast_SingleExponential_minAlfa") 00087 Forecast::SingleExponential::setMinAlfa(x->second.getDouble()); 00088 else if (x->first == "Forecast_SingleExponential_maxAlfa") 00089 Forecast::SingleExponential::setMaxAlfa(x->second.getDouble()); 00090 // Double exponential forecast method 00091 else if (x->first == "Forecast_DoubleExponential_initialAlfa") 00092 Forecast::DoubleExponential::setInitialAlfa(x->second.getDouble()); 00093 else if (x->first == "Forecast_DoubleExponential_minAlfa") 00094 Forecast::DoubleExponential::setMinAlfa(x->second.getDouble()); 00095 else if (x->first == "Forecast_DoubleExponential_maxAlfa") 00096 Forecast::DoubleExponential::setMaxAlfa(x->second.getDouble()); 00097 else if (x->first == "Forecast_DoubleExponential_initialGamma") 00098 Forecast::DoubleExponential::setInitialGamma(x->second.getDouble()); 00099 else if (x->first == "Forecast_DoubleExponential_minGamma") 00100 Forecast::DoubleExponential::setMinGamma(x->second.getDouble()); 00101 else if (x->first == "Forecast_DoubleExponential_maxGamma") 00102 Forecast::DoubleExponential::setMaxGamma(x->second.getDouble()); 00103 // Bullshit 00104 else 00105 logger << "Warning: Unrecognized parameter '" << x->first << "'" << endl; 00106 } 00107 catch (exception &e) 00108 { 00109 // Avoid throwing errors during the initialization! 00110 logger << "Error: " << e.what() << endl; 00111 } 00112 catch (...) 00113 { 00114 logger << "Error: unknown exception" << endl; 00115 } 00116 00117 try 00118 { 00119 // Initialize the metadata. 00120 Forecast::metadata = new MetaClass( 00121 "demand", 00122 "demand_forecast", 00123 Object::createString<Forecast>); 00124 ForecastBucket::metadata = new MetaClass( // No factory method for this class 00125 "demand", 00126 "demand_forecastbucket"); 00127 ForecastSolver::metadata = new MetaClass( 00128 "solver", 00129 "solver_forecast", 00130 Object::createString<ForecastSolver>); 00131 00132 // Get notified when a calendar is deleted 00133 FunctorStatic<Calendar,Forecast>::connect(SIG_REMOVE); 00134 00135 // Register the Python extensions 00136 PyThreadState *myThreadState = PyGILState_GetThisThreadState(); 00137 if (!Py_IsInitialized() || !myThreadState) 00138 throw RuntimeException("Python isn't initialized correctly"); 00139 try 00140 { 00141 // Get the global lock. 00142 PyEval_RestoreThread(myThreadState); 00143 // Register new Python data types 00144 if (PythonForecast::initialize(PythonInterpreter::getModule())) 00145 throw RuntimeException("Error registering Python forecast extension"); 00146 if (PythonForecastBucket::initialize(PythonInterpreter::getModule())) 00147 throw RuntimeException("Error registering Python forecastbucket extension"); 00148 if (PythonForecastSolver::initialize(PythonInterpreter::getModule())) 00149 throw RuntimeException("Error registering Python forecastsolver extension"); 00150 } 00151 // Release the global lock when leaving the function 00152 catch (...) 00153 { 00154 PyEval_ReleaseLock(); 00155 throw; // Rethrow the exception 00156 } 00157 PyEval_ReleaseLock(); 00158 } 00159 catch (exception &e) 00160 { 00161 // Avoid throwing errors during the initialization! 00162 logger << "Error: " << e.what() << endl; 00163 } 00164 catch (...) 00165 { 00166 logger << "Error: unknown exception" << endl; 00167 } 00168 00169 // Return the name of the module 00170 return name; 00171 } 00172 00173 } // end namespace