00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "sp_plpexecutor.h"
00013 #include <cmath>
00014 #include <ctime>
00015
00016 namespace faudes {
00017
00018
00019 ProposingExecutor::ProposingExecutor(void) : LoggingExecutor() {
00020 mPValid=false;
00021 }
00022
00023
00024
00025 void ProposingExecutor::Clear(void){
00026 LoggingExecutor::Clear();
00027 mSimEvents.Clear();
00028 mPValid=false;
00029 }
00030
00031
00032
00033 const SimEventAttribute& ProposingExecutor::EventAttribute(Idx index) const {
00034 return mSimEvents.Attribute(index);
00035 }
00036
00037
00038 void ProposingExecutor::EventAttribute(Idx index, const SimEventAttribute& rAttr) {
00039 mSimEvents.Attribute(index,rAttr);
00040 }
00041
00042
00043 void ProposingExecutor::Alphabet(const sEventSet& rAlphabet) {
00044
00045 mSimEvents=rAlphabet;
00046
00047 mSimEvents.InsertSet(LoggingExecutor::Alphabet());
00048 }
00049
00050
00051 void ProposingExecutor::ResetProposer(long int seed){
00052 FD_DS("ProposingExecutor::ResetProposer()");
00053
00054 if(seed == 0) seed = static_cast<long>(time(NULL));
00055 ran_init(seed);
00056
00057 EventSet::Iterator eit;
00058 const EventSet aevents=ActiveEventSet(CurrentParallelState());
00059 for(eit=Alphabet().Begin(); eit!=Alphabet().End(); ++eit){
00060 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00061 pattr->mScheduledFor=tpTime::UnDef;
00062 pattr->mDelayFor=tpTime::UnDef;
00063 pattr->mExpiresAt=0;
00064 if(pattr->IsPriority()) continue;
00065 if(!pattr->IsStochastic()) continue;
00066 Schedule(*eit,pattr);
00067 }
00068
00069 mPValid=false;
00070 }
00071
00072
00073 void ProposingExecutor::Reset(long int seed){
00074 FD_DS("ProposingExecutor::Reset()");
00075 LoggingExecutor::Reset();
00076 mSimEvents.InsertSet(LoggingExecutor::Alphabet());
00077 ResetProposer(seed);
00078 FD_DS("ProposingExecutor::Reset(): done");
00079 }
00080
00081
00082
00083 std::string ProposingExecutor::EventStatesToString() const {
00084 std::stringstream retstr;
00085 EventSet::Iterator eit;
00086 for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit){
00087 const SimEventAttribute attr= mSimEvents.Attribute(*eit);
00088 retstr<< "% simulation state: "<< ExpandString(mSimEvents.Str(*eit),FD_NAMELEN) << ": ";
00089 retstr<< "enabled: " << ExpandString(EnabledEventTime(*eit).Str(),FD_NAMELEN) << ": ";
00090 if(attr.IsPriority()) {
00091 retstr<< "priority: " << attr.Priority().mPriority;
00092 }
00093 if(attr.IsStochastic()) {
00094 retstr<< "stochastic: " << SimStochasticEventAttribute::TStr(attr.Stochastic().mType) ;
00095 retstr<< " scheduled " << tpTime::Str(attr.mScheduledFor);
00096 retstr<< " expires " << tpTime::Str(attr.mExpiresAt);
00097 retstr<< " delta. " << tpTime::Str(attr.mDelayFor);
00098 }
00099 if( eit!= --mSimEvents.End()) {
00100 retstr << std::endl;
00101 }
00102 }
00103 return retstr.str();
00104 }
00105
00106
00107
00108
00109 bool ProposingExecutor::ExecuteTime(tpTime::Type duration){
00110 FD_DS("ProposingExecutor::ExecuteTime(): LoggingExecutor to execute time "<< duration);
00111 if(!LoggingExecutor::ExecuteTime(duration)) return false;
00112
00113 EventSet::Iterator eit;
00114 for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit) {
00115 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00116
00117 if(!pattr->IsStochastic()) continue;
00118
00119 if(pattr->mScheduledFor!=tpTime::UnDef)
00120 if(pattr->mScheduledFor!=tpTime::Max)
00121 pattr->mScheduledFor -= duration;
00122 if(pattr->mExpiresAt!=tpTime::UnDef)
00123 if(pattr->mExpiresAt!=tpTime::Max)
00124 pattr->mExpiresAt -= duration;
00125
00126 if(pattr->Stochastic().mType==SimStochasticEventAttribute::Trigger) {
00127 pattr->mReferenceInterval.PositiveLeftShift(duration);
00128 }
00129
00130 if(pattr->Stochastic().mType==SimStochasticEventAttribute::Delay) {
00131 if(!pattr->mReferenceInterval.Empty()) {
00132 tpTime::Type delay = duration - pattr->mReferenceInterval.LB();
00133 if(delay>0) pattr->mDelayFor-=delay;
00134 pattr->mReferenceInterval.PositiveLeftShift(duration);
00135 }
00136 }
00137
00138 if(pattr->mExpiresAt<=0) Schedule(*eit,pattr);
00139 }
00140 FD_DS("ProposingExecutor::ExecuteTime(): LoggingExecutor to execute time: done ");
00141
00142 if(!mPValid) return true;
00143
00144 if(mProposal.Time==tpTime::Max) return true;
00145
00146 if(mProposal.Time < duration) { mPValid=false; return true;}
00147
00148 mProposal.Time-=duration;
00149 mPValid= (mProposal.Time>0) || (mProposal.Event!=0);
00150 return true;
00151 }
00152
00153
00154 bool ProposingExecutor::ExecuteEvent(Idx event){
00155 FD_DS("ProposingExecutor::ExecuteEvent(): LoggingExecutor to execute event "<< mSimEvents.Str(event));
00156
00157
00158 if(!LoggingExecutor::ExecuteEvent(event)) return false;
00159 FD_DS("ProposingExecutor::ExecuteEvent(): executed "<< EventName(event));
00160
00161
00162 const EventSet newActiveEvents=ActiveEventSet(CurrentParallelState());
00163 FD_DS("ProposingExecutor::ExecuteEvent(): new active events "<< newActiveEvents.ToString());
00164
00165
00166
00167 EventSet::Iterator eit;
00168 for(eit=mSimEvents.Begin(); eit!=mSimEvents.End(); ++eit) {
00169 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00170
00171 if(!pattr->IsStochastic()) continue;
00172
00173 if(pattr->Stochastic().mType==SimStochasticEventAttribute::Trigger) {
00174 TimeInterval gtime=EnabledGuardTime(*eit);
00175 gtime.Canonical();
00176 if(gtime!=pattr->mReferenceInterval) {
00177 FD_DS("ProposingExecutor::ExecuteEvent(): invalidating trigger type event "<< EStr(*eit));
00178 pattr->mExpiresAt = 0;
00179 }
00180 }
00181
00182 if(pattr->Stochastic().mType==SimStochasticEventAttribute::Delay) {
00183 TimeInterval etime=EnabledEventTime(*eit);
00184 etime.Canonical();
00185 pattr->mReferenceInterval=etime;
00186 pattr->mScheduledFor=tpTime::UnDef;
00187 pattr->mExpiresAt=tpTime::Max;
00188 tpTime::Type schedule= etime.LB()+ pattr->mDelayFor;
00189 if(etime.In(schedule)) {
00190 pattr->mScheduledFor=schedule;
00191 pattr->mExpiresAt=pattr->mScheduledFor+1;
00192 FD_DS("ProposingExecutor::ExecuteEvent(): delay event " << EStr(*eit) << ": etime "
00193 << etime.Str() << " scheduled " << schedule);
00194 }
00195 }
00196
00197 if(*eit==event) {
00198 FD_DS("ProposingExecutor::ExecuteEvent(): invalidating state for executed event "<< EStr(*eit));
00199 pattr->mExpiresAt = 0;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 if(newActiveEvents.Exists(*eit))
00223 if(pattr->mExpiresAt<=0) Schedule(*eit,pattr);
00224 }
00225
00226
00227 mPValid=false;
00228
00229 FD_DS("ProposingExecutor::ExecuteEvent(): done");
00230 return true;
00231 }
00232
00233
00234
00235 bool ProposingExecutor::ExecuteTransition(const TimedEvent& executeEvent){
00236
00237 if(!ExecuteTime(executeEvent.Time)) return false;
00238 if(executeEvent.Event==0) return true;
00239 if(!ExecuteEvent(executeEvent.Event)) return false;
00240
00241 return true;
00242 }
00243
00244
00245
00246
00247
00248 const TimedEvent& ProposingExecutor::ProposeNextTransition(void){
00249
00250 FD_DS("ProposingExecutor::ProposeNextTransition()");
00251
00252
00253 if(mPValid) return mProposal;
00254
00255
00256 mPValid=true;
00257
00258
00259 EventSet::Iterator eit;
00260 TimeInterval enabledInterval=EnabledInterval();
00261 TimeInterval enabledTime=EnabledTime();
00262 const EventSet enabledEvents = EnabledEvents();
00263
00264
00265 FD_DS("\n" << EventStatesToString());
00266 FD_DS("ProposingExecutor::ProposeNextTransition(): current time: " <<
00267 CurrentTime());
00268 FD_DS("ProposingExecutor::ProposeNextTransition(): timed state: " <<
00269 CurrentParallelTimedStateStr());
00270 FD_DS("ProposingExecutor::ProposeNextTransition(): active events: " <<
00271 ActiveEventSet(CurrentParallelState()).ToString());
00272 FD_DS("ProposingExecutor::ProposeNextTransition(): enabled interval: " <<
00273 enabledInterval.Str());
00274 FD_DS("ProposingExecutor::ProposeNextTransition(): enabled time: " <<
00275 enabledTime.Str());
00276 FD_DS("ProposingExecutor::ProposeNextTransition(): enabled events: " << std::endl <<
00277 EnabledEvents().ToString());
00278
00279
00280 Idx candidate=0;
00281 std::vector<faudes::Idx> candidates;
00282 tpTime::Type passtime=0;
00283
00284
00285 long int prio = -1;
00286 for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit) {
00287 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00288 if(!pattr->IsPriority()) continue;
00289
00290 if(pattr->Priority().mPriority >prio) {
00291 prio= pattr->Priority().mPriority;
00292 candidate=*eit;
00293 candidates.clear();
00294 candidates.push_back(candidate);
00295 }
00296
00297 if((pattr->Priority().mPriority ==prio) && (prio>=0))
00298 candidates.push_back(*eit);
00299 }
00300
00301
00302 if(candidates.size()>1) {
00303 candidate=candidates[ran_uniform_int(0,candidates.size())];
00304 }
00305
00306
00307 if(candidate>0) {
00308 FD_DS("ProposingExecutor::ProposeNextTransition(): propose by priority: " << mSimEvents.Str(candidate));
00309 mProposal.Event=candidate;
00310 mProposal.Time=0;
00311 return mProposal;
00312 }
00313
00314
00315 tpTime::Type occurence = -1;
00316 for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit){
00317 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00318 if(!pattr->IsStochastic()) continue;
00319 if(pattr->mScheduledFor == tpTime::UnDef) continue;
00320 if(enabledInterval.In(pattr->mScheduledFor)) {
00321
00322 if(pattr->mScheduledFor < occurence || occurence < 0) {
00323 occurence= pattr->mScheduledFor;
00324 candidate=*eit;
00325 candidates.clear();
00326 candidates.push_back(candidate);
00327 }
00328
00329 if(pattr->mScheduledFor == occurence)
00330 candidates.push_back(*eit);
00331 }
00332 }
00333
00334
00335 if(candidates.size()>1) {
00336 candidate=candidates[ran_uniform_int(0,candidates.size())];
00337 }
00338
00339
00340 if(candidate>0) {
00341 FD_DS("ProposingExecutor::ProposeNextTransition(): propose by stochastic: " << mSimEvents.Str(candidate) << " for " << tpTime::Str(occurence));
00342 mProposal.Event=candidate;
00343 mProposal.Time=occurence;
00344 return mProposal;
00345 }
00346
00347
00348 if(!enabledTime.Empty()) {
00349
00350 passtime=enabledInterval.UB();
00351 if(enabledInterval.Empty()) passtime=0;
00352
00353 if(enabledInterval.UBincl()) passtime+=tpTime::Step;
00354
00355 if(!enabledTime.In(passtime)) passtime-=tpTime::Step;
00356
00357 if(enabledTime.UBinf() && enabledInterval.UBinf()) passtime=tpTime::Max;
00358
00359
00360
00361 if(passtime!=0) {
00362 FD_DS("ProposingExecutor::ProposeNextTransition(): propose to pass time: "<< tpTime::Str(passtime));
00363 mProposal.Event=0;
00364 mProposal.Time=passtime;
00365 return mProposal;
00366 }
00367 }
00368
00369
00370 prio =0;
00371 for(eit=enabledEvents.Begin(); eit!=enabledEvents.End(); ++eit){
00372 SimEventAttribute* pattr= mSimEvents.Attributep(*eit);
00373 if(!pattr->IsPriority()) continue;
00374
00375 if(pattr->Priority().mPriority >prio || prio==0) {
00376 prio= pattr->Priority().mPriority;
00377 candidate=*eit;
00378 candidates.clear();
00379 candidates.push_back(candidate);
00380 }
00381
00382 if((pattr->Priority().mPriority ==prio) && (prio <0))
00383 candidates.push_back(*eit);
00384 }
00385
00386
00387 if(candidates.size()>1) {
00388 candidate=candidates[ran_uniform_int(0,candidates.size())];
00389 }
00390
00391
00392 if(candidate>0) {
00393 FD_DS("ProposingExecutor::ProposeNextTransition(): propose by priority: " << mSimEvents.Str(candidate));
00394 mProposal.Event=candidate;
00395 mProposal.Time=passtime;
00396 return mProposal;
00397 }
00398
00399
00400 if(IsDeadlocked()){
00401 FD_DS("ProposingExecutor::ProposeNextTransition(): Deadlocked");
00402 mProposal.Event=0;
00403 mProposal.Time=tpTime::UnDef;
00404 return mProposal;
00405 }
00406
00407
00408 FD_DS("ProposingExecutor::ProposeNextTransition(): Lifelock");
00409 mProposal.Event=0;
00410 mProposal.Time=tpTime::Step;
00411 return mProposal;
00412 }
00413
00414
00415
00416 TimedEvent ProposingExecutor::ExecuteNextTransition(void){
00417 FD_DS("ProposingExecutor::ExecuteNextTransition() *********************************************************** ");
00418
00419 tpTime::Type currentTime=0;
00420 TimedEvent execTimedEvent;
00421
00422
00423
00424
00425 while(true){
00426
00427
00428 execTimedEvent = ProposeNextTransition();
00429
00430
00431 if((execTimedEvent.Event==0) && (execTimedEvent.Time==0)) break;
00432 if(IsDeadlocked()) break;
00433
00434
00435 ExecuteTransition(execTimedEvent);
00436
00437
00438 if(execTimedEvent.Event!=0) break;
00439
00440
00441 currentTime+=execTimedEvent.Time;
00442
00443 }
00444
00445
00446 if(execTimedEvent.Event!=0) {
00447 execTimedEvent.Time=currentTime;
00448 return execTimedEvent;
00449 }
00450
00451
00452 execTimedEvent.Time=tpTime::UnDef;
00453 execTimedEvent.Event=0;
00454 return execTimedEvent;
00455 }
00456
00457
00458
00459
00460 tpTime::Type ProposingExecutor::Schedule(Idx event, SimEventAttribute* pattr) {
00461
00462 if(!pattr->IsStochastic()) {
00463 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): no stoxchastic attribute found");
00464 pattr->mScheduledFor=tpTime::UnDef;
00465 return tpTime::UnDef;
00466 }
00467
00468 if(pattr->mExpiresAt>0) {
00469 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): event not expired");
00470 return pattr->mScheduledFor;
00471 }
00472
00473 tpTime::Type recentschedule=pattr->mScheduledFor;
00474 pattr->mScheduledFor=tpTime::UnDef;
00475 pattr->mExpiresAt=tpTime::UnDef;
00476 pattr->mDelayFor=tpTime::UnDef;
00477 pattr->mReferenceInterval.SetEmpty();
00478
00479 TimeInterval atarget;
00480 atarget.SetPositive();
00481
00482 if(pattr->Stochastic().mType == SimStochasticEventAttribute::Trigger) {
00483 atarget.Intersect(EnabledGuardTime(event));
00484 atarget.Canonical();
00485 }
00486
00487 if(atarget.Empty()) {
00488 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): empty target");
00489 return tpTime::UnDef;
00490 }
00491
00492 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): for target " << atarget.Str());
00493 double occtime=-1;
00494 std::vector<double> pdfparavec=pattr->Stochastic().mParameter;
00495 switch(pattr->Stochastic().mPdf){
00496
00497 case SimStochasticEventAttribute::Exponential:
00498 occtime=ran_exponential(pdfparavec[0],atarget.LB(),atarget.UB());
00499 break;
00500
00501 case SimStochasticEventAttribute::Gauss:
00502 occtime=ran_gauss(pdfparavec[0],pdfparavec[1],atarget.LB(),atarget.UB());
00503 break;
00504
00505 case SimStochasticEventAttribute::Uniform: {
00506 TimeInterval utarget;
00507 utarget.LB(static_cast<tpTime::Type>(pdfparavec[0]));
00508 utarget.UB(static_cast<tpTime::Type>(pdfparavec[1]));
00509 utarget.UBincl(false);
00510 utarget.LBincl(true);
00511 utarget.Intersect(atarget);
00512 if(utarget.Empty()) {
00513 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): uniform pdf: empty target");
00514 return tpTime::UnDef;
00515 }
00516 occtime=ran_uniform(utarget.LB(),utarget.UB());
00517 }
00518 break;
00519
00520 case SimStochasticEventAttribute::Vector:
00521 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << ") internal error: no valid stochastic defs");
00522 return tpTime::UnDef;
00523 break;
00524 }
00525
00526 if(occtime < 0) {
00527 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): sampling failed: A");
00528 return tpTime::UnDef;
00529 }
00530
00531 long int round= static_cast<unsigned long>(occtime/tpTime::Step + 0.5);
00532 tpTime::Type schedule = static_cast<tpTime::Type>(round*tpTime::Step);
00533 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): random sample " << schedule
00534 << "(" << occtime << ")");
00535
00536 switch(pattr->Stochastic().mType){
00537
00538 case SimStochasticEventAttribute::Trigger:
00539
00540 if(!atarget.In(schedule)) schedule+=tpTime::Step;
00541 if(!atarget.In(schedule)) schedule-=2*tpTime::Step;
00542 if(!atarget.In(schedule)) schedule= tpTime::UnDef;
00543
00544 if(!atarget.In(schedule)) {
00545 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): sampling failed: B");
00546 return tpTime::UnDef;
00547 }
00548
00549 pattr->mScheduledFor=schedule;
00550 pattr->mExpiresAt=atarget.UB();
00551 pattr->mDelayFor=tpTime::UnDef;
00552 pattr->mReferenceInterval=atarget;
00553 break;
00554
00555 case SimStochasticEventAttribute::Extern:
00556 pattr->mScheduledFor=schedule;
00557 if(recentschedule!=tpTime::UnDef)
00558 pattr->mScheduledFor+=recentschedule;
00559 pattr->mExpiresAt=pattr->mScheduledFor+1;
00560 pattr->mDelayFor=tpTime::UnDef;
00561 pattr->mReferenceInterval.SetEmpty();
00562 if(pattr->mScheduledFor<0) {
00563 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): re-sampling");
00564 return Schedule(event,pattr);
00565 }
00566 break;
00567
00568 case SimStochasticEventAttribute::Delay:
00569 TimeInterval etime=EnabledEventTime(event);
00570 etime.Canonical();
00571 FD_DS("ProposingExecutor::Schedule(" << EStr(event) << "): delay type: etime "
00572 << etime.Str() << " delayfor " << schedule);
00573 pattr->mDelayFor=schedule;
00574 pattr->mReferenceInterval=etime;
00575 pattr->mScheduledFor=tpTime::UnDef;
00576 pattr->mExpiresAt=tpTime::Max;
00577 schedule+=etime.LB();
00578 if(etime.In(schedule)) {
00579 pattr->mScheduledFor=schedule;
00580 pattr->mExpiresAt=pattr->mScheduledFor+1;
00581 }
00582 return pattr->mScheduledFor;
00583 }
00584
00585 return pattr->mScheduledFor;
00586 }
00587
00588
00589
00590
00591 void ProposingExecutor::DoWrite(TokenWriter& rTw, const std::string& rLabel, const Type* pContext) const {
00592 (void) pContext;
00593 std::string label=rLabel;
00594 if(label=="") label = "Executor";
00595 rTw.WriteBegin(label);
00596 ParallelExecutor::DoWriteGenerators(rTw);
00597 Conditions().Write(rTw,"Conditions",this);
00598 mSimEvents.Write(rTw,"SimEventAttributes");
00599 rTw.WriteEnd(label);
00600 }
00601
00602
00603 void ProposingExecutor::DoRead(TokenReader& rTr, const std::string& rLabel, const Type* pContext) {
00604 (void) pContext;
00605 FD_DC("ProposingExecutor::DoRead(rTr, " << rLabel<<")");
00606 std::string label=rLabel;
00607 if(label=="") label = "Executor";
00608 rTr.SeekBegin(label);
00609
00610 while(!rTr.Eos(label)) {
00611
00612 Token token;
00613 rTr.Peek(token);
00614
00615 if(token.Type()==Token::Begin)
00616 if(token.StringValue()=="Generators") {
00617 ParallelExecutor::DoReadGenerators(rTr);
00618 continue;
00619 }
00620
00621 if(token.Type()==Token::Begin)
00622 if(token.StringValue()=="Conditions") {
00623 SimConditionSet conditions;
00624 conditions.Read(rTr,"Conditions",this);
00625 Conditions(conditions);
00626 continue;
00627 }
00628
00629 if(token.Type()==Token::Begin)
00630 if(token.StringValue()=="SimEventAttributes") {
00631 mSimEvents.Read(rTr,"SimEventAttributes");
00632 continue;
00633 }
00634
00635 std::stringstream errstr;
00636 errstr << "Invalid token, generators, conditions or simeventattribute section expected, " << rTr.FileLine();
00637 throw Exception("ProposingExecutor::DoRead", errstr.str(), 502);
00638 }
00639 rTr.SeekEnd(label);
00640 Reset();
00641 }
00642
00643
00644
00645 bool ProposingExecutor::RevertToStep(Idx step) {
00646 FD_DX("ProposingExecutor(" << this << ")::RevertToStep("<< step << ")");
00647
00648 bool res=LoggingExecutor::RevertToStep(step);
00649
00650 if(!res) return false;
00651
00652 ResetProposer();
00653
00654 return true;
00655 }
00656
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767