Salome HOME
Merge V8_3_BR & rnv/win_swig_generation branches
[modules/yacs.git] / src / engine / PlayGround.cxx
1 // Copyright (C) 2006-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PlayGround.hxx"
21 #include "Runtime.hxx"
22
23 #include <set>
24 #include <map>
25 #include <sstream>
26 #include <iomanip>
27 #include <numeric>
28 #include <algorithm>
29
30 using namespace YACS::ENGINE;
31
32 std::string PlayGround::printSelf() const
33 {
34   std::ostringstream oss;
35   std::size_t sz(0);
36   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
37     sz=std::max(sz,(*it).first.length());
38   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
39     {
40       oss << " - " << std::setw(10) << (*it).first << " : " << (*it).second << std::endl;
41     }
42   return oss.str();
43 }
44
45 void PlayGround::loadFromKernelCatalog()
46 {
47   Runtime *r(getRuntime());
48   if(!r)
49     throw Exception("PlayGround::loadFromKernelCatalog : no runtime  !");
50   std::vector< std::pair<std::string,int> > data(r->getCatalogOfComputeNodes());
51   setData(data);
52 }
53
54 void PlayGround::setData(const std::vector< std::pair<std::string,int> >& defOfRes)
55 {
56   _data=defOfRes;
57   checkCoherentInfo();
58 }
59
60 int PlayGround::getNumberOfCoresAvailable() const
61 {
62   int ret(0);
63   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
64     ret+=(*it).second;
65   return ret;
66 }
67
68 int PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const
69 {
70   if(nbCoresPerCont<1)
71     throw Exception("PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap : invalid nbCoresPerCont. Must be >=1 !");
72   int ret(0);
73   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
74     ret+=(*it).second/nbCoresPerCont;
75   return ret;
76 }
77
78 std::vector<int> PlayGround::computeOffsets() const
79 {
80   std::size_t sz(_data.size()),i(0);
81   std::vector<int> ret(sz+1); ret[0]=0;
82   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++,i++)
83     ret[i+1]=ret[i]+(*it).second;
84   return ret;
85 }
86
87 void PlayGround::checkCoherentInfo() const
88 {
89   std::set<std::string> s;
90   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
91     {
92       s.insert((*it).first);
93       if((*it).second<0)
94         throw Exception("Presence of negative int value !");
95     }
96   if(s.size()!=_data.size())
97     throw Exception("host names entries must be different each other !");
98 }
99
100 std::vector<bool> PlayGround::FromUItoVB(unsigned int sz, unsigned int v)
101 {
102   std::vector<bool> ret(sz);
103   unsigned int p(1);
104   for(std::size_t i=0;i<sz;i++)
105     {
106       ret[i]=p&v;
107       p<<=1;
108     }
109   return ret;
110 }
111
112 unsigned int PlayGround::FromVBtoUI(const std::vector<bool>& v)
113 {
114   std::size_t sz(v.size());
115   unsigned int ret(0);
116   for(std::size_t i=0;i<sz;i++)
117     {
118       if(v[i])
119         ret+=1u<<i;
120     }
121   return ret;
122 }
123
124 std::vector<int> PlayGround::GetIdsMatching(const std::vector<bool>& bigArr, const std::vector<bool>& pat)
125 {
126   std::vector<int> ret;
127   std::size_t szp(pat.size());
128   std::size_t sz(bigArr.size()/szp);
129   for(std::size_t i=0;i<sz;i++)
130     {
131       std::vector<bool> t(bigArr.begin()+i*szp,bigArr.begin()+(i+1)*szp);
132       if(t==pat)
133         ret.push_back(i);
134     }
135   return ret;
136 }
137
138 std::vector<int> PlayGround::BuildVectOfIdsFromVecBool(const std::vector<bool>& v)
139 {
140   std::size_t sz(std::count(v.begin(),v.end(),true)),i(0);
141   std::vector<int> ret(sz);
142   std::vector<bool>::const_iterator it(v.begin());
143   while(i<sz)
144     {
145       it=std::find(it,v.end(),true);
146       ret[i++]=std::distance(v.begin(),it);
147       it++;
148     }
149   return ret;
150 }
151
152 void PlayGround::highlightOnIds(const std::vector<int>& coreIds, std::vector<bool>& v) const
153 {
154   if(v.size()!=getNumberOfCoresAvailable())
155     throw Exception("PlayGround::highlightOnIds : oops ! invalid size !");
156   for(std::vector<int>::const_iterator it=coreIds.begin();it!=coreIds.end();it++)
157     v[*it]=true;
158 }
159
160 /*! 
161  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
162  */
163 std::vector<bool> PlayGround::getFetchedCores(int nbCoresPerWorker) const
164 {
165   int nbCores(getNumberOfCoresAvailable());
166   std::vector<bool> ret(nbCores,false);
167   if(nbCoresPerWorker==1)
168     std::fill(ret.begin(),ret.end(),true);
169   else
170     {
171       std::size_t posBg(0);
172       for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
173         {
174           int nbElemsToPutOn(((*it).second/nbCoresPerWorker)*nbCoresPerWorker);
175           std::fill(ret.begin()+posBg,ret.begin()+posBg+nbElemsToPutOn,true);
176           posBg+=(*it).second;
177         }
178     }
179   return ret;
180 }
181 /*!
182  * follow getMaxNumberOfContainersCanBeHostedWithoutOverlap method
183  */
184 std::vector<std::size_t> PlayGround::getWorkerIdsFullyFetchedBy(int nbCoresPerComp, const std::vector<bool>& coreFlags) const
185 {
186   std::size_t posBg(0),posWorker(0);
187   std::vector<std::size_t> ret;
188   for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
189     {
190       int nbWorker((*it).second/nbCoresPerComp);
191       for(int j=0;j<nbWorker;j++,posWorker++)
192         {
193           std::vector<bool>::const_iterator it2(std::find(coreFlags.begin()+posBg+j*nbCoresPerComp,coreFlags.begin()+posBg+(j+1)*nbCoresPerComp,false));
194           if(it2==coreFlags.begin()+posBg+(j+1)*nbCoresPerComp)
195             ret.push_back(posWorker);
196         }
197       posBg+=(*it).second;
198     }
199   return ret;
200 }
201
202 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PlayGround::partition(const std::vector< std::pair<const PartDefinition *,double> >& parts) const
203 {
204   std::size_t sz(parts.size()),szs(getNumberOfCoresAvailable());
205   if(sz==0)
206     return std::vector< YACS::BASES::AutoRefCnt<PartDefinition> >();
207   if(sz==1)
208     {
209       const PartDefinition *pd(parts[0].first);
210       if(!pd)
211         throw Exception("Presence of null pointer as part def  0 !");
212       YACS::BASES::AutoRefCnt<PartDefinition> ret(pd->copy());
213       std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret2(1,ret);
214       return ret2;
215     }
216   if(sz>31)
217     throw Exception("PlayGround::partition : not implemented yet for more than 31 ! You need to pay for it :)");
218   std::vector<bool> zeArr(szs*sz,false);
219   std::size_t i(0);
220   for(std::vector< std::pair<const PartDefinition *,double> >::const_iterator it=parts.begin();it!=parts.end();it++,i++)
221     {
222       const PartDefinition *pd((*it).first);
223       if(!pd)
224         throw Exception("Presence of null pointer as part def !");
225       if(pd->getPlayGround()!=this)
226         throw Exception("Presence of non homogeneous playground !");
227       if((*it).second<=0.)
228         throw Exception("Invalid weight !");
229       std::vector<bool> bs(pd->getCoresOn());
230       for(std::size_t j=0;j<szs;j++)
231         zeArr[j*sz+i]=bs[j];
232     }
233   std::set<unsigned int> ss;
234   for(std::size_t i=0;i<szs;i++)
235     {
236       std::vector<bool> vb(zeArr.begin()+i*sz,zeArr.begin()+(i+1)*sz);
237       ss.insert(FromVBtoUI(vb));
238     }
239   std::vector< std::vector<int> > retIds(sz);
240   for(std::set<unsigned int>::const_iterator i=ss.begin();i!=ss.end();i++)
241     {
242       std::vector<bool> code(FromUItoVB(sz,*i));// for this configuration which parts are considered
243       std::vector<int> locIds(GetIdsMatching(zeArr,code));
244       std::vector<int> partsIds(BuildVectOfIdsFromVecBool(code));
245       if(partsIds.empty())
246         continue;
247       std::vector<double> wg;
248       std::vector<int> nbCores2;
249       for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++)
250         {
251           wg.push_back(parts[*it].second);
252           nbCores2.push_back(parts[*it].first->getNbCoresPerCompo());
253         }
254       std::vector< std::vector<int> > ress(splitIntoParts(locIds,nbCores2,wg));
255       std::size_t k(0);
256       for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++,k++)
257         {
258           retIds[*it].insert(retIds[*it].end(),ress[k].begin(),ress[k].end());
259         }
260     }
261   //
262   std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret(sz);
263   for(std::size_t i=0;i<sz;i++)
264     {
265       std::set<int> s(retIds[i].begin(),retIds[i].end());
266       std::vector<int> v(s.begin(),s.end());
267       ret[i]=PartDefinition::BuildFrom(this,(parts[i].first)->getNbCoresPerCompo(),v);
268     }
269   return ret;
270 }
271
272 std::vector<int> sortArr(const std::vector<int>& v)
273 {
274   std::multimap<int,int> m;
275   int i(v.size()-1);
276   for(std::vector<int>::const_reverse_iterator it=v.rbegin();it!=v.rend();it++)
277     m.insert(std::pair<int,int>(*it,i--));
278   std::vector<int> ret(m.size());
279   i=0;
280   for(std::multimap<int,int>::const_reverse_iterator it=m.rbegin();it!=m.rend();it++)// reverse -> sort from biggest to the finest
281     ret[i++]=(*it).second;
282   return ret;
283 }
284
285 std::vector< std::vector<int> > PlayGround::splitIntoParts(const std::vector<int>& coreIds, const std::vector<int>& nbCoresConso, const std::vector<double>& weights) const
286 {
287   double wgs(std::accumulate(weights.begin(),weights.end(),0.));
288   std::size_t sz(nbCoresConso.size());
289   if(sz!=weights.size())
290     throw Exception("PlayGround::splitIntoParts : internal error !");
291   if(sz==0)
292     return std::vector< std::vector<int> >();
293   int totalSpace(coreIds.size());
294   std::vector< std::vector<int> > ret(sz);
295   std::vector<int> fromBigToTiny(sortArr(nbCoresConso));// start to treat the coarse grain to finish with fine grain
296   std::vector<bool> zeArr(getNumberOfCoresAvailable(),false);
297   highlightOnIds(coreIds,zeArr);
298   int nbOfCoresToSplit(coreIds.size());
299   std::size_t ii(fromBigToTiny.size());
300   for(std::vector<int>::const_iterator it=fromBigToTiny.begin();it!=fromBigToTiny.end();it++,ii--)
301     {
302       int maxNbOfCores((int)(totalSpace*weights[*it]/wgs));// now try to find in zeArr at most maxNbOfCores cores
303       ret[*it]=takePlace(maxNbOfCores,nbCoresConso[*it],zeArr,ii==1);
304     }
305   return ret;
306 }
307
308 std::vector<int> PlayGround::takePlace(int maxNbOfCoresToAlloc, int nbCoresPerShot, std::vector<bool>& distributionOfCores, bool lastOne) const
309 {
310   if(maxNbOfCoresToAlloc<1)
311     throw Exception("PlayGround::takePlace : internal error ! no space to alloc !");
312   int tmpMaxNbOfCoresToAlloc(maxNbOfCoresToAlloc);
313   if(lastOne)
314     tmpMaxNbOfCoresToAlloc=std::max(tmpMaxNbOfCoresToAlloc,(int)std::count(distributionOfCores.begin(),distributionOfCores.end(),true));
315   std::vector<int> ret;
316   std::vector<int> offsets(computeOffsets());
317   int nbFullItem(0);
318   std::size_t sz(offsets.size()-1);
319   for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;i++)
320     {
321       int d(offsets[i+1]-offsets[i]);
322       if(nbCoresPerShot>d)
323         continue;
324       std::vector<bool> target(nbCoresPerShot,true);
325       for(int j=0;j<=d-nbCoresPerShot && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;)
326         {
327           std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot);
328           if(t==target)
329             {
330               nbFullItem++;
331               tmpMaxNbOfCoresToAlloc-=nbCoresPerShot;
332               std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot,false);
333               for(int k=offsets[i]+j;k<offsets[i]+j+nbCoresPerShot;k++)
334                 ret.push_back(k);
335               j+=nbCoresPerShot;
336             }
337           else
338             j++;
339         }
340     }
341   if(nbFullItem>0)
342     return ret;
343   if(nbCoresPerShot<=1)
344     throw Exception("PlayGround::takePlace : internal error !");
345   // not enough contiguous place. Find the first wider contiguous place
346   for(int kk=std::min(nbCoresPerShot-1,tmpMaxNbOfCoresToAlloc);kk>=1;kk--)
347     {
348       for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=kk;i++)
349         {
350           int d(offsets[i+1]-offsets[i]);
351           if(kk>d)
352             continue;
353           std::vector<bool> target(kk,true);
354           for(int j=0;j<=d-kk && tmpMaxNbOfCoresToAlloc>=kk;)
355             {
356               std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk);
357               if(t==target)
358                 {
359                   nbFullItem++;
360                   tmpMaxNbOfCoresToAlloc-=kk;
361                   std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk,false);
362                   for(int k=offsets[i]+j;k<offsets[i]+j+kk;k++)
363                     ret.push_back(k);
364                   return ret;
365                 }
366               else
367                 j++;
368             }
369         }
370     }
371   throw Exception("PlayGround::takePlace : internal error ! All cores are occupied !");
372 }
373
374 int PlayGround::fromWorkerIdToResId(int workerId, int nbProcPerNode) const
375 {
376   std::size_t sz2(_data.size());
377   std::vector<int> deltas(sz2+1); deltas[0]=0;
378   for(std::size_t i=0;i<sz2;i++)
379     deltas[i+1]=deltas[i]+(_data[i].second)/nbProcPerNode;
380   int zePos(0);
381   while(zePos<sz2 && (workerId<deltas[zePos] || workerId>=deltas[zePos+1]))
382     zePos++;
383   if(zePos==sz2)
384     zePos=workerId%sz2;
385   return zePos;
386 }
387
388 /*! 
389  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
390  */
391 std::string PlayGround::deduceMachineFrom(int workerId, int nbProcPerNode) const
392 {
393   int zePos(fromWorkerIdToResId(workerId,nbProcPerNode));
394   return _data[zePos].first;
395 }
396
397 /*! 
398  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, PlayGround::getFetchedCores and PartDefinition::computeWorkerIdsCovered
399  */
400 int PlayGround::getNumberOfWorkers(int nbCoresPerWorker) const
401 {
402   return getMaxNumberOfContainersCanBeHostedWithoutOverlap(nbCoresPerWorker);
403 }
404
405 PlayGround::~PlayGround()
406 {
407 }
408
409 //////////////////////
410
411 PartDefinition::PartDefinition(const PlayGround *pg, int nbOfCoresPerComp):_nbOfCoresPerComp(nbOfCoresPerComp)
412 {
413   _pg.takeRef(pg);
414 }
415
416 PartDefinition::PartDefinition(const PartDefinition& other):_pg(other._pg),_nbOfCoresPerComp(other._nbOfCoresPerComp)
417 {
418 }
419
420 PartDefinition::~PartDefinition()
421 {
422 }
423
424 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PartDefinition::partition(const std::vector< double >& wgs) const
425 {
426   std::size_t sz(wgs.size());
427   std::vector< std::pair<const PartDefinition *,double> > elts(sz);
428   for(std::size_t i=0;i<sz;i++)
429     elts[i]=std::pair<const PartDefinition *,double>(this,wgs[i]);
430   return getPlayGround()->partition(elts);
431 }
432
433 YACS::BASES::AutoRefCnt<PartDefinition> PartDefinition::BuildFrom(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& coreIds)
434 {
435   int spaceSz(pg->getNumberOfCoresAvailable()),sz(coreIds.size());
436   if(sz>spaceSz)
437     throw Exception("PartDefinition::BuildFrom : error 1 !");
438   if(sz==0)
439     throw Exception("PartDefinition::BuildFrom : error 2 !");
440   int zeStart(coreIds.front()),zeEnd(coreIds.back());
441   if(zeStart<0 || zeEnd<zeStart)
442     throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK !");
443   for(std::size_t i=0;i<sz-1;i++)
444     if(coreIds[i+1]<coreIds[i])
445       throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK 2 !");
446   if(zeEnd-zeStart+1!=sz)
447     {
448       YACS::BASES::AutoRefCnt<PartDefinition> pd(new NonContigPartDefinition(pg,nbOfCoresPerComp,coreIds));
449       return pd;
450     }
451   if(sz==spaceSz)
452     {
453       YACS::BASES::AutoRefCnt<PartDefinition> pd(new AllPartDefinition(pg,nbOfCoresPerComp));
454       return pd;
455     }
456   YACS::BASES::AutoRefCnt<PartDefinition> pd(new ContigPartDefinition(pg,nbOfCoresPerComp,zeStart,zeEnd+1));
457   return pd;
458 }
459
460 void PartDefinition::stashPart(int nbCoresStashed, double weightOfRemain, YACS::BASES::AutoRefCnt<PartDefinition>& pdStashed, YACS::BASES::AutoRefCnt<PartDefinition>& pdRemain) const
461 {
462   if(nbCoresStashed<=0)
463     throw Exception("stashPart : Invalid nbCoresStashed value !");
464   if(weightOfRemain<=0.)
465     throw Exception("stashPart : Invalid weight !");
466   std::vector<bool> coresOn(getCoresOn());
467   int nbCoresAvailable(std::count(coresOn.begin(),coresOn.end(),true));
468   std::vector<int> ids(PlayGround::BuildVectOfIdsFromVecBool(coresOn));
469   if(nbCoresAvailable==0)
470     throw Exception("PartDefinition::stashPart : no available cores !");
471   if(nbCoresAvailable<=nbCoresStashed)
472     {
473       int n0((int)(1./(1.+weightOfRemain)*nbCoresAvailable)); n0=std::max(n0,1);
474       int n1(nbCoresAvailable-n0);
475       if(n1<=0)
476         {
477           pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids);
478           pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids);
479         }
480       else
481         {
482           std::vector<int> ids0(ids.begin(),ids.begin()+n0),ids1(ids.begin()+n0,ids.end());
483           pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
484           pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
485         }
486     }
487   else
488     {
489       std::vector<int> ids0(ids.begin(),ids.begin()+nbCoresStashed),ids1(ids.begin()+nbCoresStashed,ids.end());
490       pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
491       pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
492     }
493 }
494
495 /*! 
496  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
497  */
498 std::vector<std::size_t> PartDefinition::computeWorkerIdsCovered(int nbCoresPerComp) const
499 {
500   std::vector<bool> coresOn(getCoresOn());
501   return _pg->getWorkerIdsFullyFetchedBy(nbCoresPerComp,coresOn);
502 }
503
504 //////////////////////
505
506 ContigPartDefinition::ContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, int zeStart, int zeStop):PartDefinition(pg,nbOfCoresPerComp),_start(zeStart),_stop(zeStop)
507 {
508   if(_start<0 || _stop<_start || _stop>getSpaceSize())
509     throw Exception("ContigPartDefinition constructor : Invalid input values");
510 }
511
512 ContigPartDefinition::ContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other),_start(other._start),_stop(other._stop)
513 {
514 }
515
516 std::string ContigPartDefinition::printSelf() const
517 {
518   std::ostringstream oss;
519   oss << "Contiguous : start=" << _start << " stop=" << _stop;
520   return oss.str();
521 }
522
523 std::vector<bool> ContigPartDefinition::getCoresOn() const
524 {
525   std::vector<bool> ret(getSpaceSize(),false);
526   for(int i=_start;i<_stop;i++)
527     ret[i]=true;
528   return ret;
529 }
530
531 ContigPartDefinition *ContigPartDefinition::copy() const
532 {
533   return new ContigPartDefinition(*this);
534 }
535
536 int ContigPartDefinition::getNumberOfCoresConsumed() const
537 {
538   return _stop-_start;
539 }
540
541 //////////////////////
542
543 NonContigPartDefinition::NonContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& ids):PartDefinition(pg,nbOfCoresPerComp),_ids(ids)
544 {
545   checkOKIds();
546 }
547
548 NonContigPartDefinition::NonContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other)
549 {
550 }
551
552 std::string NonContigPartDefinition::printSelf() const
553 {
554   std::ostringstream oss;
555   oss << "Non contiguous : ";
556   for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
557     oss << *it << ", ";
558   return oss.str();
559 }
560
561 std::vector<bool> NonContigPartDefinition::getCoresOn() const
562 {
563   std::vector<bool> ret(getSpaceSize(),false);
564   for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
565     ret[*it]=true;
566   return ret;
567 }
568
569 NonContigPartDefinition *NonContigPartDefinition::copy() const
570 {
571   return new NonContigPartDefinition(*this);
572 }
573
574 int NonContigPartDefinition::getNumberOfCoresConsumed() const
575 {
576   return _ids.size();
577 }
578
579 void NonContigPartDefinition::checkOKIds() const
580 {
581   int maxVal(getSpaceSize());
582   if(_ids.empty())
583     return;
584   int val(_ids.front());
585   if(val<0 || val>=maxVal)
586     throw Exception("checkOKIds : error 2 !");
587   std::size_t sz(_ids.size());
588   for(std::size_t i=0;i<sz-1;i++)
589     {
590       if(_ids[i+1]<=_ids[i])
591         throw Exception("checkOKIds : error 1 !");
592       if(_ids[i+1]>=maxVal)
593         throw Exception("checkOKIds : error 3 !");
594     }
595 }
596
597 //////////////////////
598
599 AllPartDefinition::AllPartDefinition(const AllPartDefinition& other):PartDefinition(other)
600 {
601 }
602
603 std::string AllPartDefinition::printSelf() const
604 {
605   std::ostringstream oss;
606   oss << "All";
607   return oss.str();
608 }
609
610 std::vector<bool> AllPartDefinition::getCoresOn() const
611 {
612   std::vector<bool> ret(getSpaceSize(),true);
613   return ret;
614 }
615
616 AllPartDefinition *AllPartDefinition::copy() const
617 {
618   return new AllPartDefinition(*this);
619 }
620
621 int AllPartDefinition::getNumberOfCoresConsumed() const
622 {
623   return getSpaceSize();
624 }
625
626 //////////////////////
627  
628  std::vector<int> ForTestOmlyHPContCls::getIDS() const
629  {
630    std::size_t sz(_ids.size());
631    std::vector<int> ret(sz);
632    for(std::size_t i=0;i<sz;i++)
633      ret[i]=_ids[i];
634    return ret;
635  }