From 297cea3d51680be2a2bd9e37ad5911eb4614d2cf Mon Sep 17 00:00:00 2001 From: Sukrit Kalra Date: Wed, 18 Oct 2023 11:04:44 -0700 Subject: [PATCH] Clean up old code in Tetrisched. --- .../include/tetrisched/Expression.hpp | 437 +----- schedulers/tetrisched/src/CPLEXSolver.cpp | 195 --- schedulers/tetrisched/src/Expression.cpp | 1323 ----------------- 3 files changed, 4 insertions(+), 1951 deletions(-) diff --git a/schedulers/tetrisched/include/tetrisched/Expression.hpp b/schedulers/tetrisched/include/tetrisched/Expression.hpp index 43519acb..d7befdd9 100644 --- a/schedulers/tetrisched/include/tetrisched/Expression.hpp +++ b/schedulers/tetrisched/include/tetrisched/Expression.hpp @@ -335,10 +335,10 @@ class AllocationExpression : public Expression { Time endTime; public: - AllocationExpression(std::string taskName, - std::vector> - partitionAssignments, - Time startTime, Time duration); + AllocationExpression( + std::string taskName, + std::vector> partitionAssignments, + Time startTime, Time duration); void addChild(ExpressionPtr child) override; ParseResultPtr parse(SolverModelPtr solverModel, Partitions availablePartitions, @@ -413,432 +413,3 @@ class LessThanExpression : public Expression { }; } // namespace tetrisched #endif // _TETRISCHED_EXPRESSION_HPP_ - -// #ifndef _EXPRESSION_HPP_ -// #define _EXPRESSION_HPP_ -// // standard C/C++ libraries -// #include -// #include -// #include -// #include -// #include -// // boost libraries -// #include -// // 3rd party libraries -// // alsched libraries -// #include "Partition.hpp" -// #include "Solver.hpp" -// #include "SolverModel.hpp" - -// using namespace std; - -// namespace alsched { - -// class Expression { -// protected: -// bool marker = false; - -// public: -// static const int ALSCHED_EXPR_EXCEPTION = 0xff; - -// virtual void clearMarkers() = 0; -// virtual tuple eval(Allocation alloc) = 0; -// virtual void addChild( -// ExpressionPtr newchld) = 0; // appends new chld to chldarr -// virtual vector > generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) = 0; -// // return the set of all eq.classes referenced by this expression -// (non-const) virtual void getEquivClasses(EquivClassSet &equivClasses) = 0; -// virtual void populatePartitions(const vector &node2part, int curtime, -// int sched_horizon) = 0; -// virtual string toString() = 0; -// virtual Allocation getResults(const Solver &solver, -// vector > > &partcap, -// int start_time) = 0; -// virtual void cacheNodeResults(const Solver &solver, -// vector > > &partcap, -// int start_time) = 0; - -// // returns interval [t_1, t_2) where this expression is meaningful -// (non-const -// // due to cache) -// virtual pair startTimeRange() = 0; -// }; - -// class SchedulingExpression : public Expression { -// protected: -// /// The Task associated with this SchedulingExpression. -// TaskPtr associatedTask; -// /// Set of candidate machines that this expression can be scheduled on. -// Partitions candidateMachines; -// /// The number of nodes that this expression requires. -// /// Note that this number cannot be more than the number of candidate -// nodes. uint32_t requiredMachines; -// /// The start time at which the expression can be scheduled. -// uint32_t startTime; -// /// The duration for which this scheduling needs to occur. -// uint32_t duration; -// /// The utility to assign to this expression. -// uint32_t utility; - -// NodesPtr _nodes; -// int _k; -// double _utility; -// int _start_time; -// double _duration; - -// // resolve() will dynamically resolve eq.classes into a set of partitions -// vector partitions; // partition number of each partition -// // array of par.var. indices that match partitions: requires a reset in -// gen() vector -// partvaridx; // partition variable for each partition. owned by -// generate() - -// vector -// cached_nodes; // all machines allocated to this nck leaf previously -// // owns cache : purges it and populates it with new results from the solver -// // resolves solver results to nodes for *this leaf and caches them -// // mutates partcap, removing from it nodes allocated to *this leaf -// virtual void cacheNodeResults(const Solver &solver, -// vector > > &partcap, -// int start_time); - -// public: -// virtual ~SchedulingExpression() {} -// SchedulingExpression(TaskPtr associatedTask, Partitions candidateMachines, -// uint32_t requiredMachines, uint32_t startTime, -// uint32_t duration, uint32_t utility) -// : associatedTask(associatedTask), -// candidateMachines(candidateMachines), -// requiredMachines(requiredMachines), -// startTime(startTime), -// duration(duration), -// utility(utility) {} -// SchedulingExpression(NodesPtr nodes, int k, double utility, int start_time, -// double duration) -// : _nodes(nodes), -// _start_time(start_time), -// _duration(duration), -// _k(k), -// _utility(utility) {} -// void addChild(ExpressionPtr newchld) { -// throw Expression::ALSCHED_EXPR_EXCEPTION; -// } -// virtual void getEquivClasses(EquivClassSet &equivClasses); -// virtual void populatePartitions(const vector &node2part, int curtime, -// int sched_horizon); -// virtual Allocation getResults(const Solver &solver, -// vector > > &partcap, -// int start_time); -// void setPartitions(vector parts) { partitions = parts; } - -// void clearMarkers() { marker = false; } -// pair startTimeRange() { -// return make_pair(_start_time, _start_time + 1); -// }; -// virtual string debugString() const; -// }; - -// class Choose : public SchedulingExpression { -// public: -// // choose machines from with utility value -// Choose(NodesPtr nodes, int k, UtilVal utilval, int start_time, -// double duration) -// : SchedulingExpression(nodes, k, utilval(start_time, duration), -// start_time, duration){}; - -// /// A Choose expression is a leaf node in the expression tree that -// represents -// /// a choice of a required number of machines from the set of candidate -// /// machines for the given duration starting at the provided start_time. -// /// Args: -// /// associatedTask: The Task associated with this Expression. -// /// candidateMachines: The set of candidate machines that this expression -// /// can be scheduled on. -// /// requiredMachines: The number of machines that this expression -// requires. -// /// Note that this number cannot be more than the number of candidate -// /// machines. -// /// startTime: The start time at which the expression can be scheduled. -// /// duration: The duration for which this scheduling needs to occur. -// /// utilityFn: A function that returns the utility of scheduling this -// /// expression expressed through the inputs of start time and -// duration. Choose(TaskPtr associatedTask, Partitions candidateMachines, -// uint32_t requiredMachines, uint32_t startTime, uint32_t duration, -// UtilityFn utilityFn) -// : SchedulingExpression(associatedTask, candidateMachines, -// requiredMachines, startTime, duration, -// utilityFn(startTime, duration)) {} - -// /// Automatically reduces the reference counts to the candidateMachines -// /// passed to the constructor. -// ~Choose() {} - -// /// Parses this Expression into a set of variables and constraints for -// /// the Solver. -// std::unique_ptr parse(SolverModelPtr solverModel, -// Partitions resourcePartitions, -// uint32_t currentTime, -// uint32_t schedulingHorizon); - -// tuple eval(Allocation alloc); -// // recursively generate a model for a solver; aggregate capacity -// constraints vector > generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr); -// virtual string toString(); -// }; - -// // class LinearChoose: public SchedulingExpression { -// // public: -// // typedef boost::shared_ptr lnckExprPtr; -// // LinearChoose(NodesPtr nodes, int k, UtilVal utilval, int start_time, -// // double duration) -// // : SchedulingExpression(nodes, k, utilval(start_time, duration), -// // start_time, duration) {}; -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector -// // > > &partcap, -// // vector -// // >& capconmap, JobPtr -// jobptr); - -// // virtual ~LinearChoose() {} -// // virtual tuple eval(Allocation alloc); -// // virtual string toString(); -// // }; - -// // class PreemptingExpression: public SchedulingExpression { -// // protected: -// // unordered_map > partition_nodes; -// // void cacheNodeResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); - -// // public: -// // PreemptingExpression(NodesPtr nodes, double utility, int start_time, -// // double duration) -// // : SchedulingExpression(nodes, static_cast(nodes->size()), -// // utility, start_time, duration) {}; -// // virtual ~PreemptingExpression() {} -// // void getEquivClasses(EquivClassSet& equivClasses) { } // No-op -// // void populatePartitions(const vector &node2part, int curtime, int -// // sched_horizon); -// // }; - -// // class KillChoose: public PreemptingExpression { -// // protected: -// // public: -// // typedef boost::shared_ptr KillChooseExprPtr; -// // KillChoose(NodesPtr nodes, UtilVal utilval, double start_time, double -// // duration) -// // : PreemptingExpression(nodes, utilval(start_time, duration), -// // start_time, duration) {} -// // virtual ~KillChoose() {} -// // virtual tuple eval(Allocation alloc); -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector -// // > > &partcap, -// // vector -// // >& capconmap, JobPtr -// jobptr); -// // virtual string toString(); - -// // }; - -// // class KillLinearChoose: public PreemptingExpression { -// // public: -// // typedef boost::shared_ptr KillLinearChooseExprPtr; -// // KillLinearChoose(NodesPtr nodes, UtilVal utilval, double start_time, -// // double duration) -// // : PreemptingExpression(nodes, utilval(start_time, duration), -// // start_time, duration) {} -// // virtual ~KillLinearChoose() {} -// // virtual tuple eval(Allocation alloc); -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector -// // > > &partcap, -// // vector -// // >& capconmap, JobPtr -// jobptr); -// // virtual string toString(); - -// // }; - -// // class UnaryOperator: public Expression { - -// // protected: -// // ExpressionPtr child; -// // public: -// // UnaryOperator() {} -// // UnaryOperator(ExpressionPtr chld) : child(chld) {} -// // virtual ~UnaryOperator() {} -// // void clearMarkers(); -// // void addChild(ExpressionPtr newchld); -// // void getEquivClasses(EquivClassSet& equivClasses); -// // void populatePartitions(const vector &node2part, int curtime, int -// // sched_horizon); Allocation getResults(const Solver &solver, -// // vector > > &partcap, -// // int start_time); -// // void cacheNodeResults(const Solver &solver, -// // vector > > &partcap, -// // int st); -// // pair startTimeRange() { return child->startTimeRange(); } -// // }; - -// // class BarrierExpr: public UnaryOperator { -// // private: -// // double barrier; -// // double start_time; // start time -// // double duration; // duration - -// // public: -// // typedef boost::shared_ptr BarrierExprPtr; -// // BarrierExpr(double barrier, double start_time, double duration); -// // BarrierExpr(double barrier, double start_time, double duration, -// // ExpressionPtr newchld); virtual ~BarrierExpr() {} virtual -// // vector > generate(SolverModelPtr m, int I, -// // vector > > &partcap, -// // vector >& capconmap, -// // JobPtr jobptr); - -// // virtual tuple eval(Allocation alloc); -// // virtual string toString(); -// // }; - -// // class ScaleExpr: public UnaryOperator { -// // private: -// // double factor; - -// // public: -// // typedef boost::shared_ptr ScaleExprPtr; -// // ScaleExpr(double factor); -// // ScaleExpr(double factor, ExpressionPtr newchld); -// // virtual ~ScaleExpr() {} -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector > > &partcap, -// // vector >& capconmap, -// // JobPtr jobptr); -// // virtual tuple eval(Allocation alloc); -// // virtual string toString(); -// // }; - -// // // Job expression : sole purpose is to pass the jobptr down to children -// // class JobExpr: public UnaryOperator { -// // private: -// // JobPtr jptr; - -// // public: -// // const JobPtr getJobPtr() const {return jptr; } -// // typedef boost::shared_ptr JobExprPtr; -// // JobExpr() {} // default ctor -// // JobExpr(JobPtr _jptr): jptr(_jptr) {} -// // JobExpr(JobPtr _jptr, ExpressionPtr _chld): jptr(_jptr), -// // UnaryOperator(_chld) { } virtual ~JobExpr() {} virtual -// // vector > generate(SolverModelPtr m, int I, -// // vector > > &partcap, -// // vector >& capconmap, -// // JobPtr jobptr); -// // virtual tuple eval(Allocation alloc) -// // {return child->eval(alloc); } -// // virtual string toString() {return child->toString();} -// // }; - -// // class MinExpression: public NnaryOperator { -// // private: -// // double cached_minU; // decision variable cache -- owned by -// getResults() -// // int minUvaridx; // decision variable index -- owned by generate() -// // // helper functions -// // double upper_bound(vector > > &partcap); - -// // public: -// // typedef boost::shared_ptr MinExprPtr; -// // MinExpression(bool homogeneous_children_nodes = false) -// // : NnaryOperator(homogeneous_children_nodes){ cached_minU = 0; -// } -// // virtual ~MinExpression() {} -// // virtual tuple eval(Allocation alloc); -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector -// // > > &partcap, -// // vector -// // >& capconmap, JobPtr -// jobptr); -// // virtual string toString(); -// // virtual Allocation getResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // virtual void cacheNodeResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // }; - -// // class MaxExpression: public NnaryOperator { -// // private: -// // map indvarmap; -// // map cached_indvarmap; - -// // public: -// // typedef boost::shared_ptr MaxExprPtr; -// // MaxExpression(bool homogeneous_children_nodes = false) -// // : NnaryOperator(homogeneous_children_nodes){} -// // virtual ~MaxExpression() {} - -// // ExpressionPtr removeChild(const ExpressionPtr &chld); -// // virtual tuple eval(Allocation alloc); -// // //recursively generate a model for a solver; aggregate capacity -// // constraints virtual vector > generate(SolverModelPtr -// m, -// // int I, -// // vector -// // > > &partcap, -// // vector -// // >& capconmap, JobPtr -// jobptr); -// // //friend ostream & operator<< (ostream &out, MaxExpression *objp); -// // virtual string toString(); -// // virtual Allocation getResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // virtual void cacheNodeResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // }; - -// // class SumExpression: public NnaryOperator { -// // private: -// // //vector indvaridx; -// // map indvarmap; -// // map cached_indvarmap; -// // public: -// // typedef boost::shared_ptr SumExprPtr; -// // SumExpression(bool homogeneous_children_nodes = false) -// // : NnaryOperator(homogeneous_children_nodes){} -// // virtual ~SumExpression() {} - -// // ExpressionPtr removeChild(const ExpressionPtr &chld); // remove -// matching -// // child ExpressionPtr removeChild(JobPtr jptr); // remove matching child -// // void addChildIfNew(ExpressionPtr newchld); // adds chld only if not -// // already present void addChildIfNew(JobPtr jptr, const -// // std::function& func); //adds a JobExpr child if -// // not already present virtual tuple eval(Allocation -// alloc); -// // virtual vector > generate(SolverModelPtr m, int I, -// // vector > > &partcap, -// // vector >& capconmap, -// // JobPtr jobptr); -// // //friend ostream & operator<< (ostream &out, SumExpression *objp); -// // virtual string toString(); -// // virtual Allocation getResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // virtual void cacheNodeResults(const Solver &solver, -// // vector > > -// // &partcap, int start_time); -// // }; -// } // namespace alsched - -// #endif diff --git a/schedulers/tetrisched/src/CPLEXSolver.cpp b/schedulers/tetrisched/src/CPLEXSolver.cpp index 4d3b12d0..cfd63a65 100644 --- a/schedulers/tetrisched/src/CPLEXSolver.cpp +++ b/schedulers/tetrisched/src/CPLEXSolver.cpp @@ -273,198 +273,3 @@ SolverSolutionPtr CPLEXSolver::solveModel() { CPLEXSolver::~CPLEXSolver() { cplexEnv.end(); } } // namespace tetrisched -// // Spend at least timeLimit sec. on optimization, but once -// // this limit is reached, quit as soon as the solution is acceptable - -// ILOMIPINFOCALLBACK5(timeLimitCallback, -// IloCplex, cplex, -// IloBool, aborted, -// IloNum, timeStart, -// IloNum, timeLimit, -// IloNum, acceptableGap) -// { -// if ( !aborted && hasIncumbent() ) { -// IloNum gap = 100.0 * abs(getMIPRelativeGap()); -// IloNum timeUsed = cplex.getCplexTime() - timeStart; -// //if ( timeUsed > 1 ) printf ("time used = %g\n", timeUsed); -// if ( timeUsed > timeLimit) { -// getEnv().out() << endl -// << "Good enough solution at " -// << timeUsed << " sec., gap = " -// << gap << "%, quitting." << endl; -// aborted = IloTrue; -// abort(); -// } -// } -// } - -// void CPLEXSolver::solve(double timeLimit) -// { - -// cplex.use(timeLimitCallback(env, cplex, IloFalse, cplex.getCplexTime(), -// timeLimit, 5.0)); - -// if (true) { -// IloNumArray initvals(env); -// cout << "[SOLVER][DEBUG] initval: "; -// for (int i=0; ivars.getSize(); i++) { -// Variable v = mptr->getVariables()[i]; -// initvals.add(v.initval); -// //cout << v.initval << " "; -// if (v.initval>0) { -// cout << v.initval << " "; -// } -// } -// cout << endl; -// //cplex.addMIPStart(this->vars, initvals, -// IloCplex::MIPStartCheckFeas); cplex.addMIPStart(this->vars, initvals, -// IloCplex::MIPStartAuto); -// } - -// if (!cplex.solve()) { -// env.error() << "FAILed to optimize LP" <vars.getSize() << " -// " << mptr->getVariables().size(); assert(this->vars.getSize() == -// mptr->getVariables().size()); -// //map > j2alloc; // jobptr -> partition -> count -// map j2alloc; - -// cplex.getValues(vals, this->vars); -// for (int i=0; igetVariables()[i]; -// if (v.partidx >= 0) { -// // partition variable --> add it, account for it -// //const JobPtr &jptr = v.jptr; -// JobPtr jptr = v.jptr; -// assert (jptr); -// if (j2alloc.find(jptr) == j2alloc.end()) { -// // initialize -// j2alloc[jptr] = Allocation(); -// cout << "[j2alloc] " << vals[i] << endl; -// j2alloc[jptr].p2c[v.partidx] = vals[i]; -// j2alloc[jptr].duration = v.duration; -// j2alloc[jptr].start_time = v.start_time; -// } else { -// assert(j2alloc[jptr].duration == v.duration); -// assert(j2alloc[jptr].start_time == v.start_time); -// j2alloc[jptr].p2c[v.partidx] += vals[i]; -// } -// } -// } -// return j2alloc; -// } - -// map CPLEXSolver::getResultsForTime(double start_time) -// { -// // extract partition variable results only -// assert(this->vars.getSize() == mptr->getVariables().size()); -// map j2alloc; -// const vector &internal_vars = mptr->getVariables(); - -// // iterate over our vars; pull only partition vars for start_time -// for (int i = 0; i < internal_vars.size(); i++) { -// const Variable &v = internal_vars[i]; -// if ((v.partidx < 0) || (v.start_time != start_time)) { -// continue; // skip all but part.vars for given start_time -// } -// // get the value from CPLEX -// IloInt val; -// val = cplex.getIntValue(this->vars[i]); -// if (val <= 0 ) -// continue; // don't get part.vars with zero assigned - -// JobPtr jptr = v.jptr; -// assert (jptr); -// if (j2alloc.find(jptr) == j2alloc.end()) { -// // initialize -// j2alloc[jptr] = Allocation(); -// j2alloc[jptr].p2c[v.partidx] = val; -// j2alloc[jptr].duration = v.duration; // copy duration tag -// j2alloc[jptr].start_time = v.start_time; // copy start_time tag -// } else { -// // note we should not see multiple durations and start_times for -// // the same job in results --> assert this -// assert(j2alloc[jptr].duration == v.duration); -// assert(j2alloc[jptr].start_time == v.start_time); -// j2alloc[jptr].p2c[v.partidx] += val; -// } -// } -// return j2alloc; -// } - -// double CPLEXSolver::getResult(int vidx) const { -// const vector &internal_vars = mptr->getVariables(); // internal -// model assert(this->vars.getSize() == internal_vars.size()); // solver -// model vars assert(0 <= vidx && vidx < internal_vars.size()); const -// Variable &v = internal_vars[vidx]; switch(v.vartype) { case VAR_INT: -// { -// IloInt val = cplex.getIntValue(this->vars[vidx]); -// return val; -// } -// case VAR_FLOAT: -// { -// IloNum val = cplex.getValue(this->vars[vidx]); -// return val; -// } -// case VAR_BOOL: -// { -// IloBool val = cplex.getIntValue(this->vars[vidx]); -// return val; -// } -// default: -// { -// IloNum val = cplex.getValue(this->vars[vidx]); -// return val; -// } -// } -// } - -// // export the stored external model -// void CPLEXSolver::exportModel(const char *fname) -// { -// cplex.exportModel(fname); -// } - -// // Export the solution to the given file. -// void CPLEXSolver::exportSolution(const char *fileName) { -// cplex.writeSolution(fileName); -// } - -// } //namespace alsched - -// #endif diff --git a/schedulers/tetrisched/src/Expression.cpp b/schedulers/tetrisched/src/Expression.cpp index af05d03d..ef1da3e4 100644 --- a/schedulers/tetrisched/src/Expression.cpp +++ b/schedulers/tetrisched/src/Expression.cpp @@ -976,1326 +976,3 @@ ParseResultPtr ScaleExpression::parse( } } // namespace tetrisched - -// // standard C/C++ libraries -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// #include -// // boost libraries -// #include -// #include -// // 3rd party libraries -// // alsched libraries -// #include "Expression.hpp" -// #include "Job.hpp" -// #include "Task.hpp" -// #include "Util.hpp" -// #include "common.hpp" - -// namespace alsched { - -// // return results for given start_time, caching ALL results and resolving -// nodes -// // Returns: Allocation object (a rectangle in space time) for the matching -// // start_time -// Allocation SchedulingExpression::getResults( -// const Solver &solver, vector > > &partcap, -// int start_time) { -// // we now have cached node results -// if (start_time == this->_start_time) { -// return Allocation(this->cached_nodes, start_time, this->_duration); -// } else { -// return Allocation(vector(), start_time, this->_duration); -// } -// } - -// // owns cache : purges it and populates it with new results from the solver -// // resolves solver results to nodes for *this leaf and caches them -// // mutates partcap, removing from it nodes allocated to *this leaf -// void SchedulingExpression::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// // only cache for our start_time -// if (this->_start_time != st) { -// return; -// } -// if (marker) { -// return; -// } -// const double sched_horizon = partcap[0].rbegin()->first + 1; -// const double end_time = -// std::min(this->_start_time + this->_duration, sched_horizon); - -// // purge any cached results -// this->cached_nodes.clear(); -// // iterate over partitions; for each partition, query result for its -// part.var. for (int pi = 0; pi < this->partitions.size(); pi++) { -// int p = this->partitions[pi]; -// int vi = this->partvaridx[pi]; -// int cnt = static_cast(solver.getResult(vi)); -// // grab a mutable ref to the time slice for nodes avail. for given p and -// t vector &nodesavail = partcap[p][this->_start_time]; if (cnt > -// nodesavail.size()) { -// cout << "[DEBUG][Choose::getResults]: " -// << "cnt = " << cnt << "\t" -// << "nodesavail size = " << nodesavail.size() << endl; -// cout << this->debugString() << endl; -// } -// assert(cnt <= nodesavail.size()); -// for (int i = 0; i < cnt; i++) { -// int node = nodesavail.back(); -// // remove this node from available nodes for the duration of this leaf -// for (double t = this->_start_time; t < end_time; t += 1) { -// vector &nodesavail_future = partcap[p][t]; -// // from this vector ref, delete node -// vector::iterator it = -// find(nodesavail_future.begin(), nodesavail_future.end(), node); -// assert(it != nodesavail_future.end()); -// nodesavail_future.erase(it); -// } -// this->cached_nodes.push_back(node); // resolve -// } -// } -// marker = true; -// } - -// std::unique_ptr Choose::parse(SolverModelPtr solverModel, -// Partitions resourcePartitions, -// uint32_t currentTime, -// uint32_t schedulingHorizon) { -// uint32_t endTime = -// std::min(this->startTime + this->duration, schedulingHorizon); -// TETRISCHED_DEBUG("Generating Choose expression for " -// << associatedTask->getTaskName() -// << " to be placed starting at time " << startTime -// << " and ending at " << endTime << "."); - -// // If the current time has moved past this expression's start time, prune -// it. if (this->startTime < currentTime) { -// TETRISCHED_DEBUG("Choose expression for " << -// associatedTask->getTaskName() -// << " is in the past. -// Pruning."); -// return std::make_unique( -// ParseResult(ParseResultType::EXPRESSION_PRUNE)); -// } -// } - -// vector > Choose::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// std::string jobName("UnnamedJob"); -// if (jobptr != nullptr) { -// jobName = jobptr->getJobName(); -// } -// TETRISCHED_DEBUG("Generating Choose expression for " << jobName); -// vector > cterms; -// vector > objf; -// this->partvaridx.clear(); // purge partition variable indices - -// // sched_horizon is one past the last valid time in partcap -// // note that map's are sorted -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// TETRISCHED_DEBUG("The Choose Expression for " -// << jobName << "will be limited from time " << curtime -// << " to " << sched_horizon << "."); -// TETRISCHED_DEBUG("The Choose Expression's start time is " << -// this->_start_time -// << ".") -// // if this branch's start_time is in the past, prune it -// if ((this->_start_time < curtime) || (this->_start_time >= sched_horizon)) -// return vector >(1, pair(0, I)); - -// // end at min(start_time + duration, sched_horizon) to avoid out-of-bounds -// in -// // partcap -// double end_time = min(this->_start_time + this->_duration, sched_horizon); -// TETRISCHED_DEBUG("The Choose Expression's end time is " << end_time << -// "."); - -// // Calculate a factor to scale the utility value so that -// // the space x time area beyond the scheduling horizon -// // do not unfairly bias very long jobs -// double utilFactor = (end_time - this->_start_time) / this->_duration; -// int sumpc0 = 0; - -// // for each partition generate a partition variable P_p -// TETRISCHED_DEBUG("The size of the partitions: " << this->partitions.size() -// << "."); -// for (int pi = 0; pi < this->partitions.size(); pi++) { -// TETRISCHED_DEBUG("Generating partition variable " << pi << "."); -// int p = this->partitions[pi]; -// // 1. calculate P_p's initial value -// const vector &nodesavail = partcap[p][this->_start_time]; - -// // TODO(atumanov): consider returning identity if no nodes are available -// // Intersect available nodes with cachednodes to get count. If no nodes -// // were previously cached => isection is empty => initval for P_p is 0 -// int pc0 = vec_isection_size(nodesavail, this->cached_nodes); -// sumpc0 += pc0; - -// string vname = "P_" + jobName + "_time_" + -// std::to_string(this->_start_time) + "_" + -// std::to_string(p); -// Variable partvar(VAR_INT, pair(0, this->_k), p, vname, -// jobptr, this->_start_time, this->_duration, -// (double)pc0); -// int vi = m->addVariable(partvar); -// // save this vi -// this->partvaridx.push_back(vi); // partvar idx matches part. idx : -// // note partition variable index order -- must match partition order - -// // aggregate demand constraint : sum(cterms) = k*I -// cterms.push_back(pair(1, vi)); - -// // aggregate supply constraint: sum(terms) <= cap(p,t) -// for (double t = this->_start_time; t < end_time; t += 1) { -// if (capconmap[p].find(t) == capconmap[p].end()) { -// capconmap[p][t] = Constraint(partcap[p][t].size(), OP_LE); -// } -// TETRISCHED_DEBUG("Adding constraint term for partition " -// << p << " at time " << t << "."); -// capconmap[p][t].addConstraintTerm(pair(1, vi)); -// } -// } -// cterms.push_back( -// pair(-this->_k, I)); // complete demand -// constraint -// m->addConstraint(Constraint(cterms, 0, OP_EQ)); // add demand constraint -// // prepare objective function: u*I -// objf.push_back(pair(this->_utility * utilFactor, I)); - -// return objf; -// } - -// vector > LinearChoose::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > cterms; -// vector > objf; -// this->partvaridx.clear(); // purge partition variable indices (owned by -// // gen()) - -// // sched_horizon is one past the last valid time in partcap -// // note that map's are sorted -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// // if this branch's start_time is in the future, prune it -// if ((this->_start_time < curtime) || (this->_start_time >= sched_horizon)) -// return vector >(1, pair(0, I)); - -// // end at the min(start_time + duration, sched_horizon) so that we do not -// go -// // beyond range in partcap -// double end_time = _start_time + _duration; -// if (sched_horizon < end_time) { -// end_time = sched_horizon; -// } - -// // Calculate a factor to scale the utility value so that -// // the space x time area beyond the scheduling horizon -// // do not unfairly bias very long jobs -// double utilFactor = (end_time - _start_time) / _duration; - -// // for each partition generate a partition variable P_p -// for (int pi = 0; pi < this->partitions.size(); pi++) { -// int p = this->partitions[pi]; -// const vector &nodesavail = partcap[p][_start_time]; -// int pc0 = vec_isection_size(nodesavail, this->cached_nodes); -// string vname = "P" + to_string(p); -// Variable partvar(VAR_INT, -// pair( -// 0, std::min((int)partcap[p][_start_time].size(), -// _k)), -// p, vname, jobptr, _start_time, _duration, (double)pc0); -// int vi = m->addVariable(partvar); -// // save this vi -// this->partvaridx.push_back(vi); // match partition index - -// // aggregate objective function: Pi * u/k -// objf.push_back(pair(_utility / (1.0 * _k) * utilFactor, -// vi)); - -// // aggregate demand constraint : sum(cterms) <= k*I -// cterms.push_back(pair(1, vi)); - -// // aggregate supply constraint: sum(terms) <= cap(p,t) -// for (double t = _start_time; t < end_time; t += 1) { -// if (capconmap[p].find(t) == capconmap[p].end()) { -// // instantiate supply constraint for p,t -// capconmap[p][t] = Constraint(partcap[p][t].size(), OP_LE); -// } -// capconmap[p][t].addConstraintTerm(pair(1, vi)); -// } -// } -// cterms.push_back(pair(-_k, I)); // complete demand -// constraint m->addConstraint(Constraint(cterms, 0, OP_LE)); // add demand -// constraint - -// return objf; -// } - -// // owns cache : purges it and populates it with new results from the solver -// // resolves solver results to nodes for *this leaf and caches them -// // mutates partcap, adding it nodes preempted for *this leaf -// void PreemptingExpression::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// // only cache for our start_time -// if (this->_start_time != st) { -// return; -// } -// if (this->marker) { -// return; -// } -// const double nodes_available_time = this->_start_time + this->_duration; -// const double sched_horizon = partcap[0].rbegin()->first + 1; - -// // no-op if nodes will be available after sched_horizon -// if (nodes_available_time > sched_horizon) { -// return; -// } - -// // purge any cached results -// this->cached_nodes.clear(); -// // iterate over partitions; for each partition, query result for its -// part.var. - -// // for each partition generate a partition variable P_p -// for (int pi = 0; pi < this->partitions.size(); pi++) { -// int p = this->partitions[pi]; -// int vi = this->partvaridx[pi]; -// auto &nodesavail = this->partition_nodes[p]; -// int cnt = static_cast(solver.getResult(vi)); -// assert(cnt >= 0); -// assert(cnt <= nodesavail.size()); - -// for (int i = 0; i < cnt; i++) { -// int m = nodesavail.back(); -// nodesavail.pop_back(); -// this->_nodes->erase(std::remove(_nodes->begin(), _nodes->end(), m), -// _nodes->end()); -// assert(m >= 0); -// assert(-(m + 1) < 0); -// this->cached_nodes.push_back(-(m + 1)); -// } -// } -// marker = true; -// } - -// vector > KillChoose::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > cterms; -// vector > objf; -// this->partvaridx.clear(); // purge partition variable indices - -// // sched_horizon is one past the last valid time in partcap -// // note that map's are sorted -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// // if this branch's start_time is in the future, prune it -// if (this->_start_time != curtime) -// return vector >(1, pair(0, I)); - -// // end at min(start_time + duration, sched_horizon) to avoid out-of-bounds -// in -// // partcap -// double end_time = _start_time + _duration; -// if (sched_horizon < end_time) { -// end_time = sched_horizon; -// } - -// double preempt_start_time = _start_time + _duration; -// double preempt_end_time = -// min(jobptr->GetAlloc().start_time + jobptr->GetAlloc().duration, -// sched_horizon); - -// // Calculate a factor to scale the utility value so that -// // the space x time area beyond the scheduling horizon -// // do not unfairly bias very long jobs -// double utilFactor = (end_time - _start_time) / _duration; -// int sumpc0 = 0; - -// // for each partition generate a partition variable P_p -// for (auto &kv : this->partition_nodes) { -// int p = kv.first; -// const auto &nodesavail = kv.second; -// /* -// cout << "[DEBUG][Choose::generate]" << nodesavail.size() << " " -// << this->cached_nodes.size() << " " << pc0 << endl; -// */ - -// string vname = "P" + to_string(p); -// Variable partvar(VAR_INT, pair(0, nodesavail.size()), p, -// vname, jobptr, _start_time, _duration, (double)0); -// int vi = m->addVariable(partvar); -// // save this vi -// this->partvaridx.push_back(vi); // partvar idx matches part. idx : -// // note partition variable index order -- must match partition order - -// // aggregate demand constraint : sum(cterms) = k*I -// cterms.push_back(pair(1, vi)); - -// // aggregate supply constraint: sum(terms) <= cap(p,t) -// for (double t = preempt_start_time; t < preempt_end_time; t += 1) { -// if (capconmap[p].find(t) == capconmap[p].end()) { -// capconmap[p][t] = Constraint(partcap[p][t].size(), OP_LE); -// } -// capconmap[p][t].addConstraintTerm(pair(-1, vi)); -// } -// } -// cterms.push_back(pair(-_k, I)); // complete demand -// constraint m->addConstraint(Constraint(cterms, 0, OP_EQ)); // add demand -// constraint -// // prepare objective function: u*I -// objf.push_back(pair(_utility * utilFactor, I)); - -// return objf; -// } - -// vector > KillLinearChoose::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > cterms; -// vector > objf; -// this->partvaridx.clear(); // purge partition variable indices - -// // sched_horizon is one past the last valid time in partcap -// // note that map's are sorted -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// // if this branch's start_time is in the future, prune it -// if (_start_time != curtime) -// return vector >(1, pair(0, I)); - -// // end at min(start_time + duration, sched_horizon) to avoid out-of-bounds -// in -// // partcap -// double end_time = _start_time + _duration; -// if (sched_horizon < end_time) { -// end_time = sched_horizon; -// } - -// double preempt_start_time = _start_time + _duration; -// double preempt_end_time = -// min(jobptr->GetAlloc().start_time + jobptr->GetAlloc().duration, -// sched_horizon); - -// // Calculate a factor to scale the utility value so that -// // the space x time area beyond the scheduling horizon -// // do not unfairly bias very long jobs -// double utilFactor = (end_time - _start_time) / _duration; -// int sumpc0 = 0; - -// // for each partition generate a partition variable P_p -// for (auto &kv : this->partition_nodes) { -// int p = kv.first; -// const auto &nodesavail = kv.second; -// /* -// cout << "[DEBUG][Choose::generate]" << nodesavail.size() << " " -// << this->cached_nodes.size() << " " << pc0 << endl; -// */ - -// string vname = "P" + to_string(p); -// Variable partvar(VAR_INT, pair(0, nodesavail.size()), p, -// vname, jobptr, _start_time, _duration, (double)0); -// int vi = m->addVariable(partvar); -// // save this vi -// this->partvaridx.push_back(vi); // partvar idx matches part. idx : -// // note partition variable index order -- must match partition order - -// // aggregate demand constraint : sum(cterms) = k*I -// objf.push_back(pair(_utility / (1.0 * _k) * utilFactor, -// vi)); cterms.push_back(pair(1, vi)); - -// // aggregate supply constraint: sum(terms) <= cap(p,t) -// for (double t = preempt_start_time; t < preempt_end_time; t += 1) { -// if (capconmap[p].find(t) == capconmap[p].end()) { -// capconmap[p][t] = Constraint(partcap[p][t].size(), OP_LE); -// } -// capconmap[p][t].addConstraintTerm(pair(-1, vi)); -// } -// } -// cterms.push_back(pair(-_k, I)); // complete demand -// constraint m->addConstraint(Constraint(cterms, 0, OP_LE)); // add demand -// constraint return objf; -// } - -// vector > MaxExpression::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > cterms; // constraint: sum(Ii)<=I -// vector > objf; -// this->indvarmap.clear(); // reset decision variable indices - -// const int curtime = partcap[0].begin()->first; -// const int sched_horizon = partcap[0].rbegin()->first + 1; - -// for (int i = 0; i < chldarr.size(); i++) { -// const ExpressionPtr &c = chldarr[i]; -// const auto &startTimes = c->startTimeRange(); - -// // if there is no intersection between scheduling range [curtime, -// // sched_horizon) and startTimes, ignore children -// if (min(sched_horizon, startTimes.second) <= -// max(curtime, startTimes.first)) { -// continue; -// } - -// string vname = "maxI" + to_string(i); -// Variable maxIvar( -// VAR_BOOL, pair(0, 1), -1, vname, jobptr, 0, 0, -// (cached_indvarmap.count(c)) ? (double)(cached_indvarmap[c]) : 0); -// int vi = m->addVariable(maxIvar); -// indvarmap[c] = vi; - -// // aggregate indicator limit constraint: sum(I_i) <= I -// cterms.push_back(pair(1, vi)); -// // no supply constraint aggregation here --> only in leafs -// vector > objfi = -// c->generate(m, vi, partcap, capconmap, jobptr); -// objf.insert(objf.end(), objfi.begin(), objfi.end()); // objf += objfi -// } -// // finalize the indicator constraint : sum(Ii) <= I -// cterms.push_back(pair(-1, I)); -// m->addConstraint(Constraint(cterms, 0, OP_LE)); - -// return objf; -// } - -// // merges allocations from children, returns allocation matching start_time -// Allocation MaxExpression::getResults( -// const Solver &solver, vector > > &partcap, -// int start_time) { -// // iterate over cached indicator variables, return alloc for one enabled -// child for (const auto &p : this->cached_indvarmap) { -// ExpressionPtr expr = p.first; -// int val = p.second; -// if (val) return expr->getResults(solver, partcap, start_time); -// } - -// // no enabled children -// return Allocation(vector(), 0, 0); -// } - -// void MaxExpression::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// for (const auto &p : this->indvarmap) { -// const ExpressionPtr &chld = p.first; -// chld->cacheNodeResults(solver, partcap, st); -// } - -// if (marker) return; - -// bool childselected = false; -// this->cached_indvarmap.clear(); - -// for (const auto &p : this->indvarmap) { -// const ExpressionPtr &chld = p.first; -// int vi = p.second; -// bool val = solver.getResult(vi); -// this->cached_indvarmap[chld] = val; -// // assert that at most one child is selected -// assert(!(childselected && val)); -// if (val) childselected = true; -// } -// marker = true; -// } - -// // Given partition capacities across all partitions and time slices, -// // return the upper bound on utility at subtree rooted in *this -// double MinExpression::upper_bound(vector > > -// &partcap) { -// double max_ub = 0; // maximum upper bound across all time slices (r.v.) - -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// for (double t = curtime; t < sched_horizon; t += 1) { -// double ub4t = DBL_MAX; // minimal upper bound for time t -// // for each time slice get all available nodes and eval -// // Iterate over all partitions to get all the nodes for a given time t -// vector nodesavail; -// for (int p = 0; p < partcap.size(); p++) { -// const vector &nodesavailpt = partcap[p][t]; -// nodesavail.insert(nodesavail.end(), nodesavailpt.begin(), -// nodesavailpt.end()); -// } -// const Allocation fullcapalloc(nodesavail, t, DBL_MAX); -// for (auto c : chldarr) { -// double child_ub = get<0>(c->eval(fullcapalloc)); -// ub4t = std::min(child_ub, ub4t); // we will pick the smallest child -// util -// } -// max_ub = std::max(max_ub, ub4t); // need the maximum smallest child util -// } -// return max_ub; -// } - -// vector > MinExpression::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// // ub: what's the maximum possible utility of the subtree rooted in *this -// // for given start_time what's the full capacity of the cluster -// // TODO(atumanov): for each time slice, eval *this on union of nodes from -// all -// // p -// // and pick max util -// this->minUvaridx = -1; // reset decision variable index -// double ub = DBL_MAX; -// // double ub = upper_bound(partcap); -// assert(ub >= 0); -// // U \in range [0; ub] -// Variable minUvar(VAR_FLOAT, pair(0, ub), -1, "minU", -// jobptr, -// 0, 0, -// cached_minU); // use cached value as initial value -// int vU = m->addVariable(minUvar); -// this->minUvaridx = vU; // save this variable -// for (const auto &c : this->chldarr) { -// vector > objfi = -// c->generate(m, I, partcap, capconmap, jobptr); -// objfi.push_back(pair(-1, vU)); // objf - 1* U >= 0 -// m->addConstraint(Constraint(objfi, 0, OP_GE)); -// } -// return vector >(1, pair(1, vU)); // objf = -// U -// } - -// Allocation MinExpression::getResults( -// const Solver &solver, vector > > &partcap, -// int start_time) { -// // recursively aggregate allocations from all children -// // if the list of nodes is non-empty, assert that the start_times are the -// same Allocation allocres(vector(), start_time, 0); // r.v. for (auto -// c : this->chldarr) { -// Allocation childalloc = c->getResults(solver, partcap, start_time); -// if (childalloc.nodes.empty()) continue; -// // got a non-empty allocation from child c for start_time -// assert(allocres.start_time == childalloc.start_time); -// // now merge the list of nodes from child into result alloc -// allocres.nodes.insert(allocres.nodes.end(), childalloc.nodes.begin(), -// childalloc.nodes.end()); -// // duration -- if already set -- match it -// if (allocres.duration > 0) -// assert(childalloc.duration == allocres.duration); -// else -// allocres.duration = childalloc.duration; -// } -// return allocres; -// } - -// void MinExpression::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// for (const auto &chld : this->chldarr) { -// chld->cacheNodeResults(solver, partcap, st); -// } -// if (marker) return; - -// this->cached_minU = solver.getResult(this->minUvaridx); -// marker = true; -// } - -// vector > SumExpression::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > cterms; -// vector > objf; -// indvarmap.clear(); - -// const int curtime = partcap[0].begin()->first; -// const int sched_horizon = partcap[0].rbegin()->first + 1; - -// for (int i = 0; i < chldarr.size(); i++) { -// const auto &c = chldarr[i]; -// const auto &startTimes = c->startTimeRange(); - -// // if there is no intersection between scheduling range [curtime, -// // sched_horizon) and startTimes, ignore children -// if (min(sched_horizon, startTimes.second) <= -// max(curtime, startTimes.first)) { -// continue; -// } - -// string vname = "sumI" + to_string(i); -// Variable sumIvar( -// VAR_BOOL, pair(0, 1), -1, vname, jobptr, 0, 0, -// (cached_indvarmap.count(c)) ? (double)(cached_indvarmap[c]) : 0); -// int vi = m->addVariable(sumIvar); -// indvarmap[c] = vi; -// // aggregate indicator constraint -// cterms.push_back(pair(1, vi)); -// vector > objfi = -// c->generate(m, vi, partcap, capconmap, jobptr); -// objf.insert(objf.end(), objfi.begin(), objfi.end()); // objf += objfi -// } -// // complete the indicator constraint -// cterms.push_back(pair(-1.0 * this->chldarr.size(), I)); -// Constraint c(cterms, 0, OP_LE); -// // m->addConstraint(Constraint(cterms, 0, OP_LE)); -// // cout << "[sum ] adding constraint :" << c.toString() << endl; -// m->addConstraint(c); - -// return objf; -// } - -// // Should be similar to MinExpr -- aggregate allocation results from all -// // children for the given start_time. Cache results for all child indicator -// // variables. -// Allocation SumExpression::getResults( -// const Solver &solver, vector > > &partcap, -// int start_time) { -// Allocation allocres(vector(), start_time, 0); // empty result alloc -// // iterate over cache, recursively aggregate results for all enabled -// children for (const auto &p : cached_indvarmap) { -// const ExpressionPtr &expr = p.first; -// auto val = p.second; -// if (val) { -// // if the child was selected -- get its allocation -// Allocation childalloc = expr->getResults(solver, partcap, start_time); -// if (childalloc.nodes.empty()) continue; -// // got a non-empty alloc from child i for start_time -> merge it -// allocres.nodes.insert(allocres.nodes.end(), childalloc.nodes.begin(), -// childalloc.nodes.end()); -// // check the start_time match -// assert(allocres.start_time == childalloc.start_time); -// // duration -- if already set -- match it -// if (allocres.duration > 0) { -// assert(childalloc.duration == allocres.duration); -// } else { -// allocres.duration = childalloc.duration; -// } -// } -// } -// return allocres; -// } - -// void SumExpression::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// for (const auto &p : this->indvarmap) { -// const ExpressionPtr &chld = p.first; -// chld->cacheNodeResults(solver, partcap, st); -// } - -// if (marker) return; - -// this->cached_indvarmap.clear(); // purge cache: cacheNodeResults owns it -// // cache results for all indicator variables -// for (const auto &p : this->indvarmap) { -// const ExpressionPtr &chld = p.first; -// int vi = p.second; // get indicator var. idx for child i -// bool val = solver.getResult(vi); // extract result for this decision -// var. this->cached_indvarmap[chld] = val; -// } -// marker = true; -// } - -// Allocation UnaryOperator::getResults( -// const Solver &solver, vector > > &partcap, -// int start_time) { -// return child->getResults(solver, partcap, start_time); -// } - -// void UnaryOperator::cacheNodeResults( -// const Solver &solver, vector > > &partcap, int -// st) { -// this->child->cacheNodeResults(solver, partcap, st); -// } - -// vector > ScaleExpr::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// // scale objf of the child by this->factor and return -// vector > objf = -// this->child->generate(m, I, partcap, capconmap, jobptr); -// for (auto &term : objf) { -// // scale the term by factor -// term.first *= factor; -// } -// return objf; -// } - -// vector > BarrierExpr::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// vector > objf = -// this->child->generate(m, I, partcap, capconmap, jobptr); - -// // sched_horizon is one past the last valid time in partcap -// // note that map's are sorted -// double curtime = partcap[0].begin()->first; -// double sched_horizon = partcap[0].rbegin()->first + 1; -// // if this branch's start_time is in the past, prune it -// if ((start_time < curtime) || (start_time >= sched_horizon)) -// return vector >(1, pair(0, I)); - -// // end at min(start_time + duration, sched_horizon) to avoid out-of-bounds -// in -// // partcap -// double end_time = start_time + duration; -// if (sched_horizon < end_time) { -// end_time = sched_horizon; -// } - -// // Calculate a factor to scale the barrier so that -// // the space x time area beyond the scheduling horizon -// // do not unfairly bias very long jobs -// double utilFactor = (end_time - start_time) / duration; - -// // add constraint: f >= barrier*I (if selected, utility must exceed barrier -// // f - barrier*I >= 0 -// objf.push_back(pair(-1.0 * barrier * utilFactor, -// I)); // add constraint term -// m->addConstraint(Constraint(objf, 0, OP_GE)); -// return vector >(1, -// pair(barrier * utilFactor, -// I)); -// } - -// // sole purpose of JobExpr is to pass the job pointer further down the expr -// tree -// // TODO(atumanov): do we still need jobptr? -// vector > JobExpr::generate( -// SolverModelPtr m, int I, vector > > &partcap, -// vector > &capconmap, JobPtr jobptr) { -// // pass through the jobptr -// return child->generate(m, I, partcap, capconmap, this->jptr); -// } - -// given a particular assignment of nodes from partitions, what's my utility -// INPUT: assigned[i] == # of nodes assigned from partition i -// aggregate node counts from all partitions in our eq.class only -// return utilval if the aggregate node count is >=k -// duration of 0 indicates branch wasn't chosen -// tuple Choose::eval(Allocation alloc) { -// // Ensure we have the right time range -// if (alloc.start_time != _start_time) return make_tuple(0.0, 0.0); - -// // Calcualte number of nodes allocated -// int nodecnt = 0; -// for (int nodeAlloc : alloc.nodes) { -// for (int nodeDesired : *(this->_nodes)) { -// if (nodeAlloc == nodeDesired) { -// nodecnt++; -// break; -// } -// } -// } -// if (nodecnt >= _k) return make_tuple(_utility, _duration); - -// return make_tuple(0.0, 0.0); -// } - -// string Choose::toString() { -// string result; -// result += "nCk({"; -// for (int i = 0; i < partitions.size(); i++) { -// result += to_string(partitions[i]) + " "; -// } -// result += "}," + to_string(_k) + "," + to_string(_utility) + ")"; -// return result; -// } -// string SchedulingExpression::debugString() const { -// string result; -// result += "nCk(m:" + to_string(marker) + ","; -// // print nodes -// result += "{n:"; -// for (int i = 0; i < _nodes->size(); i++) { -// result += to_string((*_nodes)[i]) + " "; -// } -// result += "},{p:"; -// // print partitions -// for (int i = 0; i < partitions.size(); i++) { -// result += to_string(partitions[i]) + " "; -// } -// result += "},{c:"; -// // print cached nodes, if any -// for (int i = 0; i < cached_nodes.size(); i++) { -// result += to_string(cached_nodes[i]) + " "; -// } -// result += "}," + to_string(_k) + "," + to_string(_utility); -// // add time bits : start_time and duration -// result += ", s:" + to_string(_start_time) + ", d:" + to_string(_duration); -// result += ")"; -// return result; -// } - -// // given a particular assignment of nodes from partitions, what's my utility -// // INPUT: assigned[i] == # of nodes assigned from partition i -// // aggregate node counts from all partitions in our eq.class only -// // return utilval if the aggregate node count is =k -// // duration of 0 indicates branch wasn't chosen -// tuple KillChoose::eval(Allocation alloc) { -// // Calcualte number of nodes allocated -// int nodecnt = 0; -// for (int nodeAlloc : alloc.nodes) { -// for (int nodeDesired : *(this->_nodes)) { -// if (nodeAlloc == -(nodeDesired + 1)) { -// nodecnt++; -// break; -// } -// } -// } -// if (nodecnt = _k) return make_tuple(_utility, _duration); - -// return make_tuple(0.0, 0.0); -// } - -// string KillChoose::toString() { -// string result; -// result += "KnCk({"; -// for (int i = 0; i < partitions.size(); i++) { -// result += to_string(partitions[i]) + " "; -// } -// result += "}," + to_string(_k) + "," + to_string(_utility) + ")"; -// return result; -// } - -// // evaluates LnCk given assignment of nodes from partitions -// // INPUT: assigned[i] == # of nodes assigned from partition i -// // iterate over assigned, aggregating node count from partitions of interest -// // duration of 0 indicates branch wasn't chosen -// tuple LinearChoose::eval(Allocation alloc) { -// // Ensure we have the right time range -// if (alloc.start_time != _start_time) return make_tuple(0.0, 0.0); - -// // Calcualte number of nodes allocated -// int nodecnt = 0; -// for (int nodeAlloc : alloc.nodes) { -// for (int nodeDesired : *(this->_nodes)) { -// if (nodeAlloc == nodeDesired) { -// nodecnt++; -// break; -// } -// } -// } -// assert(nodecnt <= _k); -// double ratio = static_cast(nodecnt) / _k; -// return make_tuple(ratio * _utility, _duration); -// } - -// string LinearChoose::toString() { -// string result; -// result += "LnCk({"; -// for (int i = 0; i < partitions.size(); i++) { -// result += to_string(partitions[i]) + " "; -// } -// result += "}," + to_string(_k) + "," + to_string(_utility) + ")"; -// return result; -// } - -// // given a particular assignment of nodes from partitions, what's my utility -// // INPUT: assigned[i] == # of nodes assigned from partition i -// // aggregate node counts from all partitions in our eq.class only -// // return utilval if the aggregate node count is >=k -// // duration of 0 indicates branch wasn't chosen -// tuple KillLinearChoose::eval(Allocation alloc) { -// // Ensure we have the right time range -// if (alloc.start_time != _start_time) return make_tuple(0.0, 0.0); - -// // Calcualte number of nodes allocated -// int nodecnt = 0; -// for (int nodeAlloc : alloc.nodes) { -// for (int nodeDesired : *(this->_nodes)) { -// if (nodeAlloc == -(nodeDesired + 1)) { -// nodecnt++; -// break; -// } -// } -// } -// assert(nodecnt <= _k); -// double ratio = static_cast(nodecnt) / _k; -// return make_tuple(ratio * _utility, _duration); -// } - -// string KillLinearChoose::toString() { -// string result; -// result += "KLnCk({"; -// for (int i = 0; i < partitions.size(); i++) { -// result += to_string(partitions[i]) + " "; -// } -// result += "}," + to_string(_k) + "," + to_string(_utility) + ")"; -// return result; -// } - -// // duration of 0 indicates branch wasn't chosen -// tuple MinExpression::eval(Allocation alloc) { -// double minutilrv = DBL_MAX; -// double maxduration = 0; -// if (chldarr.empty()) return make_tuple(0.0, 0.0); - -// for (auto &chld : chldarr) { -// double uv; -// double duration; -// tie(uv, duration) = chld->eval(alloc); -// if (duration <= 0) return make_tuple(0.0, 0.0); -// if (uv < minutilrv) minutilrv = uv; -// if (duration > maxduration) maxduration = duration; -// } -// return make_tuple(minutilrv, maxduration); -// } - -// string MinExpression::toString() { -// string out; -// out += "min("; -// for (const auto &chld : chldarr) { -// out += chld->toString() + ","; -// } -// out += ")"; -// return out; -// } - -// // duration of 0 indicates branch wasn't chosen -// tuple MaxExpression::eval(Allocation alloc) { -// double maxutilrv = -1; -// double maxutilduration = 0; -// for (auto &chld : chldarr) { -// double uv; -// double duration; -// tie(uv, duration) = chld->eval(alloc); -// if (duration > 0) { -// if (uv > maxutilrv) { -// maxutilrv = uv; -// maxutilduration = duration; -// } else if ((uv == maxutilrv) && (duration < maxutilduration)) { -// maxutilduration = duration; -// } -// } -// } -// if (maxutilrv < 0) // Check to see if maxutilrv was set -// return make_tuple(0.0, 0.0); -// else -// return make_tuple(maxutilrv, maxutilduration); -// } - -// string MaxExpression::toString() { -// string result; -// result += "max("; -// for (const auto &chld : this->chldarr) { -// result += chld->toString() + ","; -// } -// result += ")"; -// return result; -// } - -// void NnaryOperator::clearMarkers() { -// marker = false; -// for (auto &chld : chldarr) { -// chld->clearMarkers(); -// } -// } - -// pair NnaryOperator::startTimeRange() { -// if (cache_dirty) { -// int start = INT_MAX, end = INT_MIN; -// for (auto &chld : chldarr) { -// const pair &&chldValidRange = chld->startTimeRange(); -// start = min(start, chldValidRange.first); -// end = max(end, chldValidRange.second); -// } -// this->startTimeRangeCache.first = start; -// this->startTimeRangeCache.second = end; -// cache_dirty = false; -// } -// return this->startTimeRangeCache; // valid cache -// } - -// // INPUT: assigned[i] == # nodes assigned from partition i -// // duration of 0 indicates branch wasn't chosen -// tuple SumExpression::eval(Allocation alloc) { -// double sum = 0; -// double maxduration = 0; -// for (auto &chld : chldarr) { -// double uv; -// double duration; -// tie(uv, duration) = chld->eval(alloc); -// if (duration > 0) { -// sum += uv; -// if (duration > maxduration) { -// maxduration = duration; -// } -// } -// } -// return make_tuple(sum, maxduration); -// } - -// string SumExpression::toString() { -// string out; -// out += "sum("; -// for (const auto &chld : this->chldarr) { -// out += chld->toString() + ","; -// } -// out += ")"; -// return out; -// } - -// void NnaryOperator::addChild(ExpressionPtr newchld) { -// chldarr.push_back(newchld); -// if (!cache_dirty) { -// // update startTimeRangeCache -// pair startTimeRange = newchld->startTimeRange(); -// this->startTimeRangeCache.first = -// min(this->startTimeRangeCache.first, startTimeRange.first); -// this->startTimeRangeCache.second = -// max(this->startTimeRangeCache.second, startTimeRange.second); -// } -// } -// // specialized add new child method for JobExpr children -// void SumExpression::addChildIfNew( -// JobPtr newjptr, const std::function &func) { -// for (auto chld : this->chldarr) { -// if (JobExpr::JobExprPtr jexpr = -// boost::dynamic_pointer_cast(chld)) { -// const JobPtr jptr = jexpr->getJobPtr(); -// if (jptr == newjptr) { -// assert(jptr->GetSchedExpression() == newjptr->GetSchedExpression()); -// return; // match found, do not add -// } -// } -// } -// // matching child not found --> add -// JobExpr::JobExprPtr jexpr = boost::make_shared(newjptr); -// jexpr->addChild(func(newjptr)); -// this->addChild(jexpr); -// } - -// void SumExpression::addChildIfNew(ExpressionPtr newexprptr) { -// for (auto chld : this->chldarr) -// if (chld == newexprptr) { -// return; -// } - -// this->addChild(newexprptr); -// } -// ExpressionPtr NnaryOperator::removeChild(const ExpressionPtr &chld) { -// ExpressionPtr rv = nullptr; - -// for (int i = 0; i < this->chldarr.size(); i++) { -// if (this->chldarr[i] == chld) { -// cout << "[removeChild]: removing child at position " << i << endl; -// // found a matching child -// rv = chldarr[i]; -// chldarr.erase(chldarr.begin() + i); -// cache_dirty = true; -// break; // assuming no duplicates -// } -// } -// return rv; -// } -// // Removes an element in child array, indicator variable array, and cache -// array -// // that corresponds to specified expression -// ExpressionPtr SumExpression::removeChild(const ExpressionPtr &chld) { -// ExpressionPtr rv = NnaryOperator::removeChild(chld); -// if (rv) { -// indvarmap.erase(rv); -// cached_indvarmap.erase(rv); -// } -// return rv; -// } - -// // Removes an element in child array, indicator variable array, and cache -// array -// // that corresponds to specified expression -// ExpressionPtr MaxExpression::removeChild(const ExpressionPtr &chld) { -// ExpressionPtr rv = NnaryOperator::removeChild(chld); -// if (rv) { -// indvarmap.erase(rv); -// cached_indvarmap.erase(rv); -// } -// return rv; -// } - -// ExpressionPtr SumExpression::removeChild(JobPtr newjptr) { -// for (int i = 0; i < this->chldarr.size(); i++) { -// if (JobExpr::JobExprPtr jexpr = -// boost::dynamic_pointer_cast(chldarr[i])) { -// const JobPtr jptr = jexpr->getJobPtr(); -// if (jptr == newjptr) { -// NnaryOperator::removeChild(jexpr); -// cout << "[removeChild]: removing child at position " << i << endl; -// // found a matching child; -// indvarmap.erase(jexpr); -// cached_indvarmap.erase(jexpr); -// return jexpr; // assuming no duplicates -// } -// } -// } -// return nullptr; -// } - -// // Barrier class implementation -// BarrierExpr::BarrierExpr(double _barrier, double _start_time, -// double _duration) { -// barrier = _barrier; -// start_time = _start_time; -// duration = _duration; -// } - -// BarrierExpr::BarrierExpr(double _barrier, double _start_time, double -// _duration, -// ExpressionPtr _chld) { -// barrier = _barrier; -// start_time = _start_time; -// duration = _duration; -// child = _chld; -// } -// string BarrierExpr::toString() { -// string out; -// out = "bar(" + to_string(this->barrier) + "," + this->child->toString() + -// ")"; return out; -// } - -// void UnaryOperator::addChild(ExpressionPtr _chld) { -// // this implementation only accepts one child, hence replace -// child = _chld; -// } - -// void UnaryOperator::clearMarkers() { -// marker = false; -// child->clearMarkers(); -// } - -// // duration of 0 indicates branch wasn't chosen -// tuple BarrierExpr::eval(Allocation alloc) { -// // barrier function is a step function that evaluates to u = barrier -// double uv; -// double duration; -// tie(uv, duration) = child->eval(alloc); -// if (uv >= barrier) return make_tuple(barrier, duration); -// return make_tuple(0.0, 0.0); -// } - -// ScaleExpr::ScaleExpr(double _factor) { factor = _factor; } - -// ScaleExpr::ScaleExpr(double _factor, ExpressionPtr _chld) { -// factor = _factor; -// child = _chld; -// } -// string ScaleExpr::toString() { -// string out; -// out = -// "scale(" + to_string(this->factor) + "," + this->child->toString() + -// ")"; -// return out; -// } - -// // duration of 0 indicates branch wasn't chosen -// tuple ScaleExpr::eval(Allocation alloc) { -// double uv; -// double duration; -// tie(uv, duration) = child->eval(alloc); -// return make_tuple(factor * uv, duration); -// } - -// typedef vector BitVector; -// typedef boost::shared_array BitVectors; - -// Get all equivalence classes in expression tree -// void SchedulingExpression::getEquivClasses(EquivClassSet &equivClasses) { -// if (marker) { -// return; -// } -// marker = true; -// equivClasses.insert(*_nodes); -// } - -// void UnaryOperator::getEquivClasses(EquivClassSet &equivClasses) { -// if (marker) { -// return; -// } -// marker = true; -// child->getEquivClasses(equivClasses); -// } - -// void NnaryOperator::getEquivClasses(EquivClassSet &equivClasses) { -// if (marker) { -// return; -// } -// marker = true; -// if (homogeneous_children_nodes) { -// // optimize: we know children for each time t is identical. -// const auto &startTime = chldarr.front()->startTimeRange(); -// for (const auto &child : chldarr) { -// if (child->startTimeRange() == startTime) { -// child->getEquivClasses(equivClasses); -// } -// } -// } else { -// for (const auto &child : chldarr) { -// child->getEquivClasses(equivClasses); -// } -// } -// } - -// Fills in partitions -// void SchedulingExpression::populatePartitions(const vector &node2part, -// int curtime, int sched_horizon) -// { -// if (marker) { -// return; -// } -// marker = true; -// // Calcualte set of partitions -// unordered_set partitionSet; -// for (int id : *_nodes) { -// partitionSet.insert(node2part[id]); -// } -// // Return partitions -// partitions.assign(partitionSet.begin(), partitionSet.end()); -// } - -// void PreemptingExpression::populatePartitions(const vector &node2part, -// int curtime, int sched_horizon) -// { -// if (marker) { -// return; -// } -// SchedulingExpression::populatePartitions(node2part, curtime, -// sched_horizon); this->partition_nodes.clear(); -// // Calcualte set of partitions -// for (int id : *_nodes) { -// int partition = node2part[id]; -// this->partition_nodes[partition].push_back(id); -// } -// assert(this->partition_nodes.size() == this->partitions.size()); -// } - -// void UnaryOperator::populatePartitions(const vector &node2part, -// int curtime, int sched_horizon) { -// if (marker) { -// return; -// } -// marker = true; -// child->populatePartitions(node2part, curtime, sched_horizon); -// } - -// void NnaryOperator::populatePartitions(const vector &node2part, -// int curtime, int sched_horizon) { -// if (marker) { -// return; -// } -// marker = true; -// for (const auto &child : chldarr) { -// const auto &startTimes = child->startTimeRange(); - -// // if there is no intersection between scheduling range [curtime, -// // curtime+sched_horizon) and startTimes, ignore children -// if (min(curtime + sched_horizon, startTimes.second) <= -// max(curtime, startTimes.first)) { -// continue; -// } -// child->populatePartitions(node2part, curtime, sched_horizon); -// } -// } - -// } // namespace alsched