00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "CoinTime.hpp"
00013 #include "BCP_process.hpp"
00014
00015 #ifndef BCP_DEBUG_PRINT
00016 #define BCP_DEBUG_PRINT 0
00017 #endif
00018
00019 BCP_scheduler::BCP_scheduler():
00020 totalNumberIds_(0),
00021 freeIds_(),
00022 numNodeIds_(0),
00023 maxNodeIds_(1),
00024 maxNodeIdRatio_(1.0),
00025 maxNodeIdNum_(1)
00026 {}
00027
00028 void
00029 BCP_scheduler::setParams(double OverEstimationStatic,
00030 double SwitchToRateThreshold,
00031 double TimeRootNodeSolve,
00032 double FactorTimeHorizon,
00033 double OverEstimationRate,
00034 double MaxNodeIdRatio,
00035 int MaxNodeIdNum,
00036 int MaxSbIds,
00037 int MinSbIds)
00038 {
00039 rho_static_ = OverEstimationStatic;
00040 switch_thresh_ = SwitchToRateThreshold;
00041 numSecRateInterval_ = (int)ceil(TimeRootNodeSolve*FactorTimeHorizon);
00042 request_counts_.reserve(numSecRateInterval_+1);
00043 request_counts_.insert(request_counts_.end(), numSecRateInterval_+1, -1);
00044 request_counts_tot_ = 0;
00045 release_counts_.reserve(numSecRateInterval_+1);
00046 release_counts_.insert(release_counts_.end(), numSecRateInterval_+1, -1);
00047 release_counts_tot_ = 0;
00048 counts_ptr_ = 0;
00049 time_last_action_ = 0;
00050 static_ = true;
00051 have_rates_ = false;
00052 rho_rate_ = OverEstimationRate;
00053 maxNodeIdRatio_ = MaxNodeIdRatio;
00054 maxNodeIdNum_ = MaxNodeIdNum;
00055 maxNodeIds_ = CoinMin((int)floor(maxNodeIdRatio_ * totalNumberIds_),
00056 maxNodeIdNum_);
00057 if (maxNodeIds_ == 0) {
00058 maxNodeIds_ = 1;
00059 }
00060 maxSbIds_ = MaxSbIds;
00061
00062 minSbIds_ = MinSbIds;
00063 }
00064
00065
00066 void
00067 BCP_scheduler::add_free_ids(int numIds, const int* ids)
00068 {
00069 freeIds_.insert(freeIds_.end(), ids, ids+numIds);
00070 totalNumberIds_ += numIds;
00071 maxNodeIds_ = CoinMin((int)floor(maxNodeIdRatio_ * totalNumberIds_),
00072 maxNodeIdNum_);
00073 const double t = CoinWallclockTime();
00074 for (int i = 0; i < numIds; ++i) {
00075 sb_idle_time_[ids[i]] = 0.0;
00076 node_idle_time_[ids[i]] = 0.0;
00077 last_release_time_[ids[i]] = t;
00078 last_release_type_[ids[i]] = 0;
00079 }
00080 }
00081
00082
00083
00084 int
00085 BCP_scheduler::request_sb_ids(int reqNumIds, int* ids)
00086 {
00087
00088 update_rates(1, 0);
00089
00090 int numIds = CoinMin(reqNumIds, max_id_allocation(reqNumIds));
00091 #if (BCP_DEBUG_PRINT != 0)
00092 if (static_) {
00093 printf("SC static: req: %i given: %i total: %i node(max): %i(%i) free: %i minSb: %i maxSb: %i rho: %lf\n",
00094 reqNumIds, numIds, totalNumberIds_, numNodeIds_, maxNodeIds_,
00095 (int)freeIds_.size(), minSbIds_, maxSbIds_, rho_static_);
00096 } else {
00097 printf("SC rate: req: %i given: %i total: %i node(max): %i(%i) free: %i minSb: %i maxSb: %i rho: %lf rel_cnt: %i req_cnt: %i\n",
00098 reqNumIds, numIds, totalNumberIds_, numNodeIds_, maxNodeIds_,
00099 (int)freeIds_.size(), minSbIds_, maxSbIds_, rho_rate_,
00100 release_counts_tot_, request_counts_tot_);
00101 }
00102 #endif
00103 if (numIds==0) return 0;
00104
00105 const int newsize = freeIds_.size() - numIds;
00106 CoinDisjointCopyN(&freeIds_[newsize], numIds, ids);
00107 freeIds_.erase(freeIds_.begin()+newsize, freeIds_.end());
00108 const double t = CoinWallclockTime();
00109 for (int i = 0; i < numIds; ++i) {
00110 const int id = ids[i];
00111 if (last_release_type_[id] != 2) {
00112 sb_idle_time_[id] += t - last_release_time_[id];
00113 } else {
00114 node_idle_time_[id] += t - last_release_time_[id];
00115 }
00116 }
00117 return numIds;
00118 }
00119
00120 void
00121 BCP_scheduler::release_sb_id(int id)
00122 {
00123
00124 update_rates(0, 1);
00125 freeIds_.push_back(id);
00126 last_release_time_[id] = CoinWallclockTime();
00127 last_release_type_[id] = 1;
00128 }
00129
00130
00131
00134 int
00135 BCP_scheduler::request_node_id()
00136 {
00137 if (freeIds_.empty() || numNodeIds_ == maxNodeIds_) return -1;
00138 numNodeIds_ ++;
00139 int id = freeIds_.back();
00140 freeIds_.pop_back();
00141 return id;
00142 }
00143
00144 void
00145 BCP_scheduler::release_node_id(int id)
00146 {
00147
00148 update_rates(0, 1);
00149 freeIds_.push_back(id);
00150 last_release_time_[id] = CoinWallclockTime();
00151 last_release_type_[id] = 2;
00152 numNodeIds_--;
00153 }
00154
00155
00156
00157 void
00158 BCP_scheduler::update_idle_times()
00159 {
00160 const double t = CoinWallclockTime();
00161 for (int i = freeIds_.size()-1; i >= 0; --i) {
00162 const int id = freeIds_[i];
00163 if (last_release_type_[id] != 2) {
00164 sb_idle_time_[id] += t - last_release_time_[id];
00165 } else {
00166 node_idle_time_[id] += t - last_release_time_[id];
00167 }
00168 }
00169 }
00170
00171
00172
00173
00174 void
00175 BCP_scheduler::update_rates(int add_req, int add_rel)
00176 {
00177
00178 time_t time_now = time(NULL);
00179 if (time_now == time_last_action_) {
00180 request_counts_[counts_ptr_] += add_req;;
00181 release_counts_[counts_ptr_] += add_rel;;
00182 }
00183 else if (time_last_action_ == 0) {
00184 counts_ptr_ = 0;
00185 request_counts_[counts_ptr_] = add_req;
00186 release_counts_[counts_ptr_] = add_rel;
00187 time_last_action_ = time_now;
00188 }
00189 else {
00190 while (time_last_action_ < time_now) {
00191 request_counts_tot_ += request_counts_[counts_ptr_];
00192 release_counts_tot_ += release_counts_[counts_ptr_];
00193 counts_ptr_++;
00194 if (counts_ptr_ > numSecRateInterval_) {
00195 counts_ptr_ = 0;
00196 have_rates_ = true;
00197 }
00198 if (have_rates_) {
00199 request_counts_tot_ -= request_counts_[counts_ptr_];
00200 release_counts_tot_ -= release_counts_[counts_ptr_];
00201 }
00202 request_counts_[counts_ptr_] = 0;
00203 release_counts_[counts_ptr_] = 0;
00204
00205 time_last_action_++;
00206 }
00207 request_counts_[counts_ptr_] = add_req;
00208 release_counts_[counts_ptr_] = add_rel;
00209
00210 static_ = (!have_rates_ || freeIds_.size() >= (1.-switch_thresh_)*(totalNumberIds_-numNodeIds_) );
00211 }
00212 }
00213
00214
00215
00216 int
00217 BCP_scheduler::max_id_allocation(int numIds)
00218 {
00219 double dretval;
00220 int retval;
00221
00222
00223
00224
00225 const int numFree = freeIds_.size();
00226
00227 double expRate =
00228 (double)CoinMin(2*numNodeIds_,maxNodeIds_) / (double)numNodeIds_;
00229
00230 if (static_) {
00231 dretval = (rho_static_ * (double)(totalNumberIds_-numNodeIds_*expRate) /
00232 (double)(numNodeIds_*expRate) );
00233 }
00234 else {
00235 if (request_counts_tot_ == 0) {
00236 dretval = numFree;
00237 }
00238 else {
00239 dretval = (rho_rate_ * (double)(release_counts_tot_) /
00240 (double)(request_counts_tot_));
00241 }
00242 }
00243 retval = CoinMin(numFree, (int)floor(dretval));
00244
00245 if (numIds >= minSbIds_ && retval < minSbIds_) {
00246 retval = 0;
00247 }
00248 if (retval > maxSbIds_) {
00249 retval = maxSbIds_;
00250 }
00251
00252
00253 if (retval && (retval & 1) == 0) {
00254 --retval;
00255 }
00256
00257 return retval;
00258 }