void Write(Dictionary<TK, TV> const &a) { Write("Count = "); var len = a.Count(); Write(len); WriteChar(NewLine); if (len) { var p = a.UsedNodeHead(); Lab1: Write(p->Key); Write(", "); Write(p->Value); WriteChar(NewLine); if ((p = p->UsedNext)) goto Lab1; } }
void SimulationRun(string RunParameterNames[]) { ifstream TraceFile; bool RunValid=true; if(PrimaryProtocol==NULL) { cerr<<"RUN ERROR: No protocol specified!"<<endl; RunValid=false; } if(TraceFileName=="") { cerr<<"RUN ERROR: No trace file specified!"<<endl; RunValid=false; } if(RunValid) { TraceFile.open(TraceFileName.c_str()); if(!TraceFile.is_open()) { cerr<<"RUN ERROR: Cannot open trace file!"<<endl; RunValid=false; } else if(TraceFile.bad()||TraceFile.fail()) { cerr<<"RUN ERROR: Stream was corrupted!"<<endl; RunValid=false; } } if(!RunValid){return;}//Immediately break and cancel the run if there are execution errors. ResetGlobalVariables(); int VehicleNum,BeginTime,EndTime; float x,y; int NextSimulationTime; int VehicleNumMask=1;//The modulo of the vehicle num and this value determines whether a vehicle is omitted to get a different set of vehicles in the simulation. int VehicleNumMaskOffset=0; bool MaskExists=CheckRunVariableExists("VehicleNumMask"); bool OffsetExists=CheckRunVariableExists("VehicleNumMaskOffset"); if(MaskExists!=OffsetExists){cerr<<"ERROR: Must specify both VehicleNumMask and VehicleNumMaskOffset for this input to be effective!"<<endl;} else if(MaskExists) { VehicleNumMask=GetRunVariableInteger("VehicleNumMask"); VehicleNumMaskOffset=GetRunVariableInteger("VehicleNumMaskOffset"); } while (TraceFile >> NextSimulationTime >> VehicleNum >> x >> y >> BeginTime >> EndTime)// loop through all input { TimeMax=max(NextSimulationTime+1,TimeMax); if((--VehicleNum)%VehicleNumMask==VehicleNumMaskOffset) { VehicleNum/=VehicleNumMask; VehicleMax=max(VehicleNum+1,VehicleMax); for(int i=Vehicles.Count();i<VehicleMax;i++){Vehicles.PushObj(new Vehicle("OBU#"+to_string((long long int)i)));} Vehicle* CurrentVehicle=Vehicles[VehicleNum]; if(CurrentVehicle->v_begin_t==-1) { CurrentVehicle->v_begin_t=BeginTime; CurrentVehicle->v_begin_x=x; CurrentVehicle->v_begin_x=y; CurrentVehicle->v_end_t=EndTime; } } } OutputVariables.Set("VehicleMax",to_string((long long int)VehicleMax)); OutputVariables.Set("TimeMax",to_string((long long int)TimeMax)); OutputVariables.Set("TraceFile",TraceFileName); OutputVariables.Set("ProtocolName",ProtocolName); TraceFile.clear(); TraceFile.seekg(0, TraceFile.beg); // reposition to beginning of input file if(TraceFile.bad()||TraceFile.fail()) { cerr<<"RUN ERROR: Could not reset stream!"<<endl; RunValid=false; } int PeakAnonymitySetSize=0;//Used to calculate one of our metrics later. float PeakAnonymityDistance=0; if(CheckRunVariableExists("GlobalMessageLimit")){NetworkObject::GlobalMessageLimit=GetRunVariableInteger("GlobalMessageLimit");} SetGlobalVehicleMaxMessagePerTick(CheckRunVariableExists("VehicleMessageLimit")?GetRunVariableInteger("VehicleMessageLimit"):0); time_t SimulationBeginTime=time(NULL); RunValid=RunValid&&PrimaryProtocol->SimulationBegin(); bool TraceFileEOF=false; while(!TraceFileEOF) { TraceFile>>NextSimulationTime>>VehicleNum>>x>>y>>BeginTime>>EndTime; TraceFileEOF=TraceFile.eof(); if(!TraceFileEOF&&(TraceFile.bad()||TraceFile.fail())) { cerr<<"RUN ERROR: Stream became corrupted during simulation!"<<endl; RunValid=false; break; } if(SimulationTime==-1){SimulationTime=NextSimulationTime;}//This prevents a logic error that causes a simulation tick before the first batch of tracefile data has been processed. if(TraceFileEOF||SimulationTime!=NextSimulationTime) { RunValid=RunValid&&PrimaryProtocol->SimulationTick(); if(!RunValid){break;}//This short-circuits the execution if a critical error as occurred. //This loop adds to the average counters in each vehicle. //Average counters are processed after the simulation to get various anonymity statistics. //As such, these values are not menaingful until they have been finalized later. for(int i=0;i<VehicleMax;i++) { Vehicle* CurrentVehicle=Vehicles[i]; if(!CurrentVehicle->CurrentlyWithinSimulation()){continue;} if(CurrentVehicle->AssignedSet!=NULL) { AnonymitySet* CurrentSet=CurrentVehicle->AssignedSet; int SetSize=CurrentSet->Count(); CurrentVehicle->AverageAnonymitySetSizeCounter+=SetSize; PeakAnonymitySetSize=max(PeakAnonymitySetSize,SetSize); ArrayList<Vehicle*>* VehiclesInSet=&(CurrentSet->AnonymousVehicles); float SetDistance=0.0; for(int io=0;io<VehiclesInSet->Count();io++) { Vehicle* OtherVehicle=(*VehiclesInSet)[io]; if(CurrentVehicle==OtherVehicle){continue;} float XDist=CurrentVehicle->x-OtherVehicle->x; float YDist=CurrentVehicle->y-OtherVehicle->y; float Dist=sqrt(XDist*XDist+YDist*YDist); SetDistance+=Dist; PeakAnonymityDistance=max(PeakAnonymityDistance,Dist); } CurrentVehicle->AverageAnonymityDistanceCounter+=SetDistance/SetSize; } else{CurrentVehicle->AverageAnonymitySetSizeCounter++;} } for(int i=0;i<VehicleMax;i++) { Vehicle* CurrentVehicle=Vehicles[i]; if(SimulationTime==CurrentVehicle->v_end_t) { CurrentVehicle->v_end_x=CurrentVehicle->x; CurrentVehicle->v_end_y=CurrentVehicle->y; CurrentVehicle->v_terminated=SimulationTime; //We set ending data AFTER the protocol text so the set isn't prematurely decremented. if(CurrentVehicle->AssignedSet!=NULL){CurrentVehicle->AssignedSet->RemoveVehicle(CurrentVehicle);} } } if(TraceFileEOF){break;} SimulationTime=NextSimulationTime; } if((--VehicleNum)%VehicleNumMask==VehicleNumMaskOffset) { VehicleNum=VehicleNum/VehicleNumMask; Vehicle* CurrentVehicle=Vehicles[VehicleNum];//We decrement VehicleNum because trace files base their lists with 1 as the first index. CurrentVehicle->x=x; CurrentVehicle->y=y; } } if(RunValid) { PrimaryProtocol->SimulationEnd(); time_t SimulationRunTime=time(NULL)-SimulationBeginTime; OutputVariables.Set("RunTime",to_string(((long double)SimulationRunTime)/60.0)); //This loop adds inputs as outputs, so the resulting printed line can also reference parameters used in the run. for(int i=0;i<RunVariables.Count();i++){OutputVariables.Set(RunVariables.GetKey(i),RunVariables.Get(i));} //This loop calculates various averages. int AnonymousVehicleCount=0; int AverageAnonymitySamples=0; float AverageAnonymitySetSize=0.0; float AverageAnonymityDistance=0.0; float AverageAnonymityTime=0.0; float PeakAnonymityTime=0.0; for(int i=0;i<Vehicles.Count();i++) { Vehicle* CurrentVehicle=Vehicles[i]; if(CurrentVehicle->v_terminated==-1) { cerr<<"TERMINATE ERROR: Vehicle#"<<i<<" was supposed to terminate at "<<CurrentVehicle->v_end_t<<"/"<<SimulationTime<<endl; CurrentVehicle->v_terminated=CurrentVehicle->v_end_t; } AverageAnonymitySamples+=(CurrentVehicle->v_terminated-CurrentVehicle->v_begin_t)+1; AverageAnonymitySetSize+=CurrentVehicle->AverageAnonymitySetSizeCounter; AverageAnonymityDistance+=CurrentVehicle->AverageAnonymityDistanceCounter; if(CurrentVehicle->v_k_assign_t!=-1) { AnonymousVehicleCount++; float AnonTime=CurrentVehicle->v_terminated-CurrentVehicle->v_k_silent_t; AverageAnonymityTime+=AnonTime; PeakAnonymityTime=max(PeakAnonymityTime,AnonTime); } } if(AnonymousVehicleCount>0){AverageAnonymityTime/=AnonymousVehicleCount;} if(AverageAnonymitySamples==0) { AverageAnonymitySetSize=0.0f; AverageAnonymityDistance=0.0f; } else { AverageAnonymitySetSize/=AverageAnonymitySamples; AverageAnonymityDistance/=AverageAnonymitySamples; } OutputVariables.Set("AverageAnonymitySetSize",to_string((long double)AverageAnonymitySetSize)); OutputVariables.Set("PeakAnonymitySetSize",to_string((long long int)PeakAnonymitySetSize)); OutputVariables.Set("AverageAnonymityDistance",to_string((long double)AverageAnonymityDistance)); OutputVariables.Set("PeakAnonymityDistance",to_string((long double)PeakAnonymityDistance)); OutputVariables.Set("AverageAnonymityTime",to_string((long double)AverageAnonymityTime)); OutputVariables.Set("PeakAnonymityTime",to_string((long double)PeakAnonymityTime)); OutputVariables.Set("AnonymousVehicleCount",to_string((long long int)AnonymousVehicleCount)); OutputVariables.Set("TotalAnonymitySets",to_string((long long int)AnonymitySets.Count())); //This loop calculates the most congested networked unit. int CongestionCount=0; NetworkObject* CongestedUnit=NULL; for(int i=0;i<NetworkObjects.Count();i++) { NetworkObject* CurrentCounter=NetworkObjects[i]; int MaxPackets=CurrentCounter->NetworkMessages.GetMostPacketsTransmitted(); if(MaxPackets>CongestionCount) { CongestedUnit=CurrentCounter; CongestionCount=MaxPackets; } } if(CongestedUnit==NULL){OutputVariables.Set("PeakTrafficUnit","None");} else{OutputVariables.Set("PeakTrafficUnit",CongestedUnit->Title);} OutputVariables.Set("PeakTrafficAmount",to_string((long long int)CongestionCount)); //This loop adds the traffic counters to the list of OutputVariables. for(int i=0;i<=TOTAL_TRAFFIC_TYPES;i++){OutputVariables.Set(string("Packet Count: ")+GetEnumName((TrafficType)i),to_string((long long int)GlobalTraffic[i]));} OutputVariables.Set(string("Packet Count: Overhead"),to_string((long long int)GlobalTraffic.Overhead())); OutputVariables.Set(string("Packet Count: Overhead Ratio"),to_string((long double)GlobalTraffic.OverheadRatio())); OutputVariables.Set(string("Packet Count: Successful"),to_string((long long int)GlobalTraffic.TotalTransmitted())); OutputVariables.Set(string("Packet Count: Lost"),to_string((long long int)GlobalTraffic.TotalLost())); OutputVariables.Set(string("PacketLoss"),to_string((long double)GlobalTraffic.PacketLoss())); OutputVariables.Set(string("Throughput"),to_string((long double)GlobalTraffic.TotalTransmitted()/TimeMax)); //OUTPUT if(LegacyOutput) { cout<<"RUN:"; for(int i=0;i<MAX_PARAMETERS_PER_LINE&&RunParameterNames[i].length()>0;i++) { if(i>0){cout<<",";} cout<<RunParameterNames[i]<<"="<<setw(3)<<RunVariables.Get(RunParameterNames[i]); } cout<<": "; cout<<fixed<< "K="<<setw(5)<<setprecision(2)<<AverageAnonymitySetSize<<"("<<AnonymitySets.Count()<<"), "<< "D="<<setw(6)<<setprecision(2)<<AverageAnonymityDistance<<", "<< "T="<<setw(5)<<setprecision(2)<<AverageAnonymityTime<<", "<< "Anonymous="<<setw(4)<<AnonymousVehicleCount<<"/"<<setw(4)<<VehicleMax; for(int i=0;i<=TOTAL_TRAFFIC_TYPES;i++){cout<<", "<<GetEnumName((TrafficType)i)<<":"<<GlobalTraffic[i];} if(CongestedUnit!=NULL){cout<<", Congested: "<<CongestedUnit->Title<<"("<<CongestionCount<<")";} cout<<endl; } else if(VerboseOutput) { for(int i=0;i<OutputVariables.Count();i++) { if(i!=0){cout<<", ";} cout<<OutputVariables.GetKey(i)<<"="<<OutputVariables.Get(i); } cout<<endl; } else { //TODO: Get the output to interpret different variable types. int FormatNeedle=0;//This advances through the format string as we process each section. while(FormatNeedle<OutputFormat->size()) { //These first few lines find the next special character, or the end of the string, and OutputVariables any part of the string which was passed over. size_t FoundIndex=OutputFormat->find(OUTPUT_FORMAT_DELIMITER,FormatNeedle); if(FoundIndex==string::npos){FoundIndex=OutputFormat->size();} cout<<OutputFormat->substr(FormatNeedle,FoundIndex-FormatNeedle); FormatNeedle=FoundIndex+1; //If the end of the string was not reached, we then try to parse the next block of characters, which are special notation. if(FoundIndex<OutputFormat->size()) { FoundIndex=OutputFormat->find(OUTPUT_FORMAT_DELIMITER,FormatNeedle); if(FoundIndex==string::npos) { cerr<<"ERROR: Misformatted Output String: No Closing '"<<OUTPUT_FORMAT_DELIMITER<<"'!"<<endl; break; } string FormatSpecifierArguments("s"); size_t FoundSubIndex=OutputFormat->find(OUTPUT_FORMAT_SUB_DELIMITER,FormatNeedle); if(FoundSubIndex!=string::npos) { FormatSpecifierArguments=OutputFormat->substr(FormatNeedle,FoundSubIndex-FormatNeedle); FormatNeedle=FoundSubIndex+1; } string OutputValue("Unspecified"); string VariableName=OutputFormat->substr(FormatNeedle,FoundIndex-FormatNeedle); if(OutputVariables.HasKey(VariableName)){OutputValue=OutputVariables.Get(VariableName);} string FormatSpecifier("%"); FormatSpecifier=FormatSpecifier+FormatSpecifierArguments; char VariableTypeSpecifier=FormatSpecifier.at(FormatSpecifier.size()-1); switch(VariableTypeSpecifier) { case 'd': case 'i': case 'u': printf(FormatSpecifier.c_str(),atoi(OutputValue.c_str())); break; case 'f': case 'F': printf(FormatSpecifier.c_str(),atof(OutputValue.c_str())); break; default: printf(FormatSpecifier.c_str(),OutputValue.c_str()); break; } FormatNeedle=FoundIndex+1; } } cout<<endl<<flush;//We have to use this operator to push a newline to cout, or the Cloud9 interface will cache it in a strange way. } } //CLEANUP fflush(NULL); TraceFile.close(); while(AnonymitySets.Count()>0){delete AnonymitySets.PopObj();} while(Vehicles.Count()>0){delete Vehicles.PopObj();} }