schedulers  1.0.0
src/PruhsNLP.cpp
Go to the documentation of this file.
00001 /*
00002  Copyright 2015 Nicolas Melot
00003 
00004  This file is part of Pelib.
00005 
00006  Pelib is free software: you can redistribute it and/or modify
00007  it under the terms of the GNU General Public License as published by
00008  the Free Software Foundation, either version 3 of the License, or
00009  (at your option) any later version.
00010 
00011  Pelib is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with Pelib. If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 #include <string>
00021 
00022 #include <pelib/PruhsNLP.hpp>
00023 #include <pelib/AmplSolver.hpp>
00024 #include <pelib/Schedule.hpp>
00025 #include <pelib/XMLSchedule.hpp>
00026 #include <pelib/Scalar.hpp>
00027 #include <pelib/Vector.hpp>
00028 #include <pelib/Matrix.hpp>
00029 #include <pelib/Set.hpp>
00030 #include <pelib/Task.hpp>
00031 #include <pelib/Taskgraph.hpp>
00032 #include <pelib/Platform.hpp>
00033 #include <pelib/CastException.hpp>
00034 #include <pelib/ParseException.hpp>
00035 #include <pelib/AmplOutput.hpp>
00036 #include <pelib/PelibException.hpp>
00037 
00038 #define debug(var) cout << "[" << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "] " << #var << " = \"" << (var) << "\"" << endl;
00039 
00040 using namespace std;
00041 using namespace pelib;
00042 
00043 extern char _binary_pruhs_mod_start;
00044 extern char _binary_pruhs_mod_end;
00045 extern char _binary_pruhs_run_start;
00046 extern char _binary_pruhs_run_end;
00047 
00048 extern char _binary_pruhs_rescale_mod_start;
00049 extern char _binary_pruhs_rescale_mod_end;
00050 extern char _binary_pruhs_rescale_run_start;
00051 extern char _binary_pruhs_rescale_run_end;
00052 
00053 PruhsNLP::PruhsNLP(bool showOutput, bool showError)
00054 {
00055         param.insert(new Scalar<float>("alpha", 3));
00056         this->showError = showError;
00057         this->showOutput = showOutput;
00058 }
00059 
00060 PruhsNLP::PruhsNLP(const Algebra &param, bool showOutput, bool showError)
00061 {
00062         this->param = param;
00063         this->showError = showError;
00064         this->showOutput = showOutput;
00065 }
00066 
00067 PruhsNLP::PruhsNLP(const Taskgraph &tg, const Platform &pt, const Algebra &param, bool showOutput, bool showError)
00068 {
00069         this->taskgraph = tg;
00070         this->platform = pt;
00071         this->param = param;
00072         this->showError = showError;
00073         this->showOutput = showOutput;
00074 }
00075 
00076 Schedule
00077 PruhsNLP::schedule(const Taskgraph &tg, const Platform &pt, std::map<const string, double>& stats) const
00078 {
00079         return schedule(tg, pt, this->param, stats);
00080 }
00081 
00082 Schedule
00083 PruhsNLP::schedule(const Taskgraph &tg, const Platform &pt, const Algebra &param, std::map<const string, double>& stats) const
00084 {
00085         // Add default values, if necessary
00086         Algebra p = param;
00087         if(p.find<Scalar<float> >("alpha") == NULL)
00088         {
00089                 p.insert(new Scalar<float>("alpha", 3));
00090         }
00091         
00092         // Build input collection
00093         map<const string, const Algebra> data;
00094         data.insert(pair<const string, const Algebra>(string("platform.dat"), pt.buildAlgebra()));
00095         data.insert(pair<const string, const Algebra>(string("parameters.dat"), p));
00096 
00097         // Save and remove name vector from data
00098         Algebra taskgraph = tg.buildAlgebra(pt);
00099         const Vector<int, string> *name_ptr = taskgraph.find<Vector<int, string> >("name");
00100         if(name_ptr == NULL)
00101         {
00102                 throw PelibException("Missing tasks' name vector from taskgraph conversion to Algebra record");
00103         }
00104         Vector<int, string> name(*name_ptr);
00105         taskgraph.remove("name");
00106         data.insert(pair<const string, const Algebra>(string("taskgraph.dat"), taskgraph));
00107 
00108         // Build model and run scripts input streams
00109         stringstream model(string(&_binary_pruhs_mod_start, &_binary_pruhs_mod_end));
00110         stringstream run(string(&_binary_pruhs_run_start, &_binary_pruhs_run_end));
00111 
00112         // Run the solver for the scheduling phase
00113         const Algebra *solution = AmplSolver(model, string("model.mod"), run, data, this->showOutput, this->showError).solve(stats);
00114         if(stats.find("feasible")->second != 0)
00115         {
00116                 stats.erase(stats.find("feasible"));
00117                 map<const string, double>::iterator ii = stats.find("time");
00118                 double pruhs_time = 0;
00119                 if(ii != stats.end())
00120                 {
00121                         pruhs_time = ii->second;
00122                 }
00123 
00124                 data = map<const string, const Algebra>();
00125                 data.insert(pair<const string, const Algebra>(string("input.dat"), *solution));
00126                 delete solution;
00127 
00128                 stringstream rescale_model(string(&_binary_pruhs_rescale_mod_start, &_binary_pruhs_rescale_mod_end));
00129                 stringstream rescale_run(string(&_binary_pruhs_rescale_run_start, &_binary_pruhs_rescale_run_end));
00130                 solution = AmplSolver(rescale_model, string("model.mod"), rescale_run, data, this->showOutput, this->showError).solve(stats);
00131                 Algebra alg = Schedule::addStartTime(*solution, tg, pt);
00132 
00133                 // Insert back name vector
00134                 alg.insert(new Vector<int, string>(name));
00135                 p = alg.merge(pt.buildAlgebra());
00136 
00137                 ii = stats.find("time");
00138                 if(ii != stats.end())
00139                 {
00140                         double time = ii->second;
00141                         stats.erase(ii);
00142                         stats.insert(pair<const string, double>("time_schedule", pruhs_time));
00143                         stats.insert(pair<const string, double>("time_rescale", time));
00144                         stats.insert(pair<const string, double>("time_global", pruhs_time + time));
00145                 }
00146                 if(stats.find("feasible")->second != 0)
00147                 {
00148                         return Schedule("Pruhs NLP", tg.getName(), p);
00149                 }
00150                 else
00151                 {
00152                         return Schedule("Pruhs NLP", tg.getName(), Schedule::table());
00153                 }
00154         }
00155         else
00156         {
00157                 return Schedule("Pruhs NLP", tg.getName(), Schedule::table());
00158         }
00159 }
00160 
00161 const Algebra*
00162 PruhsNLP::solve() const
00163 {
00164         map<const string, double> stats;
00165         return new Algebra(schedule(this->taskgraph, this->platform, this->param, stats).buildAlgebra());
00166 }
00167 
00168 const Algebra*
00169 PruhsNLP::solve(map<const string, double> &stats) const
00170 {
00171         return new Algebra(schedule(this->taskgraph, this->platform, this->param, stats).buildAlgebra());
00172 }
00173 
00174 std::string
00175 PruhsNLP::getShortDescription() const
00176 {
00177         float alpha = this->param.find<Scalar<float> >("alpha")->getValue();
00178         stringstream ss;
00179 
00180         std::streamsize p = ss.precision();
00181         ss.precision(4);
00182         ss << "Pruhs-NLP." << "(a=" << alpha << ")";
00183         ss.precision(p);
00184 
00185         return ss.str();
00186 }
00187 
00188 #ifdef __cplusplus
00189 extern "C" {
00190 #endif
00191 
00192 enum config_src {BINARY, ORGAN, TASKGRAPH};
00193 
00194 struct args
00195 {
00196         double alpha;
00197         size_t fin;
00198         bool showError, showOutput;
00199         
00200 };
00201 typedef struct args args_t;
00202 
00203 static args_t
00204 parse(char **args)
00205 {
00206         args_t out;
00207         out.showError = false;
00208         out.showOutput = false;
00209         out.alpha = 3;
00210 
00211         for(; args[0] != NULL; args++)
00212         {
00213                 if(strcmp(args[0], "--show-stdout") == 0)
00214                 {
00215                         out.showOutput = true;
00216                         continue;
00217                 }
00218                 if(strcmp(args[0], "--show-stderr") == 0)
00219                 {
00220                         out.showError = true;
00221                         continue;
00222                 }
00223                 if(strcmp(args[0], "--alpha") == 0)
00224                 {
00225                         args++;
00226                         stringstream str(args[0]);
00227                         str >> out.alpha;
00228                         continue;
00229                 }
00230         }
00231 
00232         return out;
00233 }
00234 
00235 const pelib::Schedule*
00236 pelib_schedule(const pelib::Taskgraph &tg, const pelib::Platform &pt, size_t argc, char **argv, map<const string, double>& statistics)
00237 {
00238         args_t args = parse(argv);
00239         Algebra param;
00240         param.insert(new Scalar<float>("alpha", args.alpha));
00241 
00242         // Convert solver output to general schedule
00243         Schedule *sched;
00244         sched = new Schedule(PruhsNLP(param, args.showOutput, args.showError).schedule(tg, pt, statistics));
00245 
00246         return sched;
00247 }
00248 
00249 string
00250 pelib_description(size_t argc, char **argv)
00251 {
00252         args_t args = parse(argv);
00253         Algebra param;
00254         param.insert(new Scalar<float>("alpha", args.alpha));
00255 
00256         // Convert solver output to general schedule
00257         string desc;
00258         desc = PruhsNLP(param, args.showOutput, args.showError).getShortDescription();
00259 
00260         return desc;
00261 }
00262 
00263 void
00264 pelib_delete(pelib::Schedule *sched)
00265 {
00266         delete sched;
00267 }
00268 
00269 #ifdef __cplusplus
00270 }
00271 #endif
00272 
00273