schedulers  1.0.0
src/XuILP.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/XuILP.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_xu_mod_start;
00044 extern char _binary_xu_mod_end;
00045 extern char _binary_xu_run_start;
00046 extern char _binary_xu_run_end;
00047 
00048 XuILP::XuILP(bool showOutput, bool showError)
00049 {
00050         param.insert(new Scalar<float>("alpha", 3));
00051         this->showError = showError;
00052         this->showOutput = showOutput;
00053 }
00054 
00055 XuILP::XuILP(const Algebra &param, bool showOutput, bool showError)
00056 {
00057         this->param = param;
00058         this->showError = showError;
00059         this->showOutput = showOutput;
00060 }
00061 
00062 XuILP::XuILP(const Taskgraph &tg, const Platform &pt, const Algebra &param, bool showOutput, bool showError)
00063 {
00064         this->taskgraph = tg;
00065         this->platform = pt;
00066         this->param = param;
00067         this->showError = showError;
00068         this->showOutput = showOutput;
00069 }
00070 
00071 Schedule
00072 XuILP::schedule(const Taskgraph &tg, const Platform &pt, std::map<const string, double>& stats) const
00073 {
00074         return schedule(tg, pt, this->param, stats);
00075 }
00076 
00077 Schedule
00078 XuILP::schedule(const Taskgraph &tg, const Platform &pt, const Algebra &param, std::map<const string, double>& stats) const
00079 {
00080         // Add default values, if necessary
00081         Algebra p = param;
00082         if(p.find<Scalar<float> >("alpha") == NULL)
00083         {
00084                 p.insert(new Scalar<float>("alpha", 3));
00085         }
00086         
00087         // Build input collection
00088         map<const string, const Algebra> data;
00089         data.insert(pair<const string, const Algebra>(string("platform.dat"), pt.buildAlgebra()));
00090         data.insert(pair<const string, const Algebra>(string("parameters.dat"), p));
00091 
00092         // Save and remove name vector from data
00093         Algebra taskgraph = tg.buildAlgebra(pt);
00094         const Vector<int, string> *name_ptr = taskgraph.find<Vector<int, string> >("name");
00095         if(name_ptr == NULL)
00096         {
00097                 throw PelibException("Missing tasks' name vector from taskgraph conversion to Algebra record");
00098         }
00099         Vector<int, string> name(*name_ptr);
00100         taskgraph.remove("name");
00101         data.insert(pair<const string, const Algebra>(string("taskgraph.dat"), taskgraph));
00102 
00103         // Build model and run scripts input streams
00104         stringstream model(string(&_binary_xu_mod_start, &_binary_xu_mod_end));
00105         stringstream run(string(&_binary_xu_run_start, &_binary_xu_run_end));
00106 
00107         // Run the solver
00108         const Algebra *solution = AmplSolver(model, string("model.mod"), run, data, this->showOutput, this->showError).solve(stats);
00109         Algebra alg = *solution;
00110 
00111         // Insert back name vector
00112         alg.insert(new Vector<int, string>(name));
00113         p = solution->merge(pt.buildAlgebra());
00114         map<const string, double>::iterator ii = stats.find("time");
00115         if(ii != stats.end())
00116         {
00117                 double time = ii->second;
00118                 stats.erase(ii);
00119                 stats.insert(pair<const string, double>("time_schedule", time));
00120                 stats.insert(pair<const string, double>("time_global", time));
00121         }
00122         if(stats.find("feasible")->second != 0)
00123         {
00124                 return this->buildSchedule(alg, tg.getName());
00125         }
00126         else
00127         {
00128                 return Schedule("ILP Unrestricted", tg.getName(), Schedule::table());
00129         }
00130 }
00131 
00132 const Algebra*
00133 XuILP::solve() const
00134 {
00135         map<const string, double> stats;
00136         return new Algebra(schedule(this->taskgraph, this->platform, this->param, stats).buildAlgebra());
00137 }
00138 
00139 const Algebra*
00140 XuILP::solve(map<const string, double> &stats) const
00141 {
00142         return new Algebra(schedule(this->taskgraph, this->platform, this->param, stats).buildAlgebra());
00143 }
00144 
00145 std::string
00146 XuILP::getShortDescription() const
00147 {
00148         float alpha = this->param.find<Scalar<float> >("alpha")->getValue();
00149         stringstream ss;
00150 
00151         std::streamsize p = ss.precision();
00152         ss.precision(4);
00153         ss << "XuILP." << "(a=" << alpha << ")";
00154         ss.precision(p);
00155 
00156         return ss.str();
00157 }
00158 
00159 Schedule
00160 XuILP::buildSchedule(const Algebra &in, const std::string &name) const
00161 {
00162         AmplOutput output(AmplOutput::floatHandlers());
00163 
00164         Algebra alg = in;
00165 
00166         int p = alg.find<Scalar<float> >("p")->getValue();
00167         map<int, float> degree = alg.find<Vector<int, float> >("wi")->getValues();
00168         map<int, float> level = alg.find<Vector<int, float> >("level")->getValues();
00169         map<int, float> time = alg.find<Vector<int, float> >("time")->getValues();
00170         const Matrix<int, int, float> *ampl_tasks = alg.find<Matrix<int, int, float> >("tasks");
00171         map<int, map<int, float> > tasks = ampl_tasks->getValues();
00172         map<int, map<int, float> > schedule;
00173 
00174         float cumulated_time = 0;
00175         map<int, float> level_start;
00176         for(map<int, float>::iterator i = level.begin(); i != level.end(); i++)
00177         {
00178                 level_start.insert(pair<int, float>(i->first, cumulated_time));
00179                 cumulated_time += time.find(i->first)->second;
00180         }
00181 
00182         map<int, float> start;
00183         for(map<int, map<int, float> >::iterator i = tasks.begin(); i != tasks.end(); i++)
00184         {
00185                 start.insert(pair<int, float>(i->first, level_start.find(level.find(i->first)->second)->second));
00186                 for(int k = 0; k < p; k++)
00187                 {
00188                         schedule[k + 1][round(i->first)] = 0;
00189                 }
00190         }
00191 
00192         for(map<int, map<int, float> >::iterator i = tasks.begin(); i != tasks.end(); i++)
00193         {
00194                 int offset = 0;
00195                 int level = i->first;
00196                 for(map<int, float>::iterator j = i->second.begin(); j != i->second.end(); j++)
00197                 {
00198                         if(j->second != 0)
00199                         {
00200                                 int task = round(j->second);
00201                                 int wi = round(degree[task]);
00202 
00203                                 for(int k = 0; k < wi; k++)
00204                                 {
00205                                         schedule[offset + k + 1][level] = task;
00206                                 }
00207                                 offset += wi;
00208                         }
00209                 }
00210         }
00211 
00212         Vector<int, float> start_vector("start", start);
00213         alg.insert(&start_vector);
00214         Matrix<int, int, float> schedule_matrix("schedule", schedule);
00215         alg.insert(&schedule_matrix);
00216         Schedule sched("Xu ILP", name, alg);
00217 
00218         return sched;
00219 }
00220 
00221 #ifdef __cplusplus
00222 extern "C" {
00223 #endif
00224 
00225 struct args
00226 {
00227         double alpha;
00228         bool showError, showOutput;
00229         
00230 };
00231 typedef struct args args_t;
00232 
00233 static args_t
00234 parse(char **args)
00235 {
00236         args_t out;
00237         out.showError = false;
00238         out.showOutput = false;
00239         out.alpha = 3;
00240 
00241         for(; args[0] != NULL; args++)
00242         {
00243                 if(strcmp(args[0], "--show-stdout") == 0)
00244                 {
00245                         out.showOutput = true;
00246                         continue;
00247                 }
00248                 if(strcmp(args[0], "--show-stderr") == 0)
00249                 {
00250                         out.showError = true;
00251                         continue;
00252                 }
00253                 if(strcmp(args[0], "--alpha") == 0)
00254                 {
00255                         args++;
00256                         stringstream str(args[0]);
00257                         str >> out.alpha;
00258                         continue;
00259                 }
00260         }
00261 
00262         return out;
00263 }
00264 
00265 const pelib::Schedule*
00266 pelib_schedule(const pelib::Taskgraph &tg, const pelib::Platform &pt, size_t argc, char **argv, map<const string, double>& statistics)
00267 {
00268         args_t args = parse(argv);
00269         Algebra param;
00270         param.insert(new Scalar<float>("alpha", args.alpha));
00271 
00272         // Convert solver output to general schedule
00273         Schedule *sched;
00274         sched = new Schedule(XuILP(param, args.showOutput, args.showError).schedule(tg, pt, statistics));
00275 
00276         return sched;
00277 }
00278 
00279 string
00280 pelib_description(size_t argc, char **argv)
00281 {
00282         args_t args = parse(argv);
00283         Algebra param;
00284         param.insert(new Scalar<float>("alpha", args.alpha));
00285 
00286         // Convert solver output to general schedule
00287         string desc;
00288         desc = XuILP(param, args.showOutput, args.showError).getShortDescription();
00289 
00290         return desc;
00291 }
00292 
00293 void
00294 pelib_delete(pelib::Schedule *sched)
00295 {
00296         delete sched;
00297 }
00298 
00299 #ifdef __cplusplus
00300 }
00301 #endif
00302 
00303