00001 #include "BAPTVPartitioner.h"
00002
00003 using std::cout;
00004 using std::cerr;
00005 using std::endl;
00006 using std::ifstream;
00007 using std::ofstream;
00008 using std::ios;
00009 using std::setprecision;
00010
00011
00012
00013 BAPTVPartitioner::BAPTVPartitioner(BAPPackage& aPackage)
00014 : BAPPartitioner(aPackage),
00015 mNumVes(aPackage.NumVessels()),
00016 mVes(array<TVVessel>(1, mNumVes)),
00017 mNumSect(aPackage.NumSections()),
00018 mSect(array<TVSection>(1, mNumSect)),
00019 mTrans(aPackage.Transhipments()),
00020 mDist(aPackage.Distances()),
00021 mTraceFile(mPackage.PartitioningTraceFilename()),
00022 mRuntimeAnalyzer(0),
00023 mSolnExists(false)
00024 {
00025 gettimeofday(&mStartTime, NULL);
00026 array<int> temp;
00027
00028
00029 temp = aPackage.VesselLengths();
00030
00031 for (int i = 1; i <= mNumVes; i++)
00032 {
00033 TVVessel v(i, temp[i]);
00034 v.StartTimeZone(aPackage.StartTimeZone(i));
00035 v.EndTimeZone(aPackage.EndTimeZone(i));
00036 v.Arrival(aPackage.Arrival(i));
00037 v.Departure(aPackage.Departure(i));
00038
00039
00040 for (int j = 1; j <= mNumVes; j++)
00041 {
00042 if (j == i) continue;
00043
00044 if (mTrans(i, j) > 0 || mTrans(j, i) > 0)
00045 {
00046 v.AddNeighbour(j);
00047 v.AddTranshipment(mTrans(i, j));
00048 v.AddTranshipment(mTrans(j, i));
00049 }
00050 }
00051
00052 v.Export(mTrans(0, i));
00053 v.Import(mTrans(i, 0));
00054 mVes[i] = v;
00055 }
00056
00057
00058 temp = aPackage.SectionLengths();
00059
00060 for (int i = 1, t = aPackage.NumTimeZones(); i <= mNumSect; i++)
00061 mSect[i] = TVSection(i, t, temp[i]);
00062
00063 ReadParameterFile();
00064 }
00065
00066
00067 BAPTVPartitioner::~BAPTVPartitioner()
00068 {
00069
00070 }
00071
00072
00073 void BAPTVPartitioner::Print(const int& aWidth,
00074 const int& aDetail) const
00075 {
00076 cout << "--== BAPTVPartitioner ==--" << endl
00077 << " ID = " << ID() << endl
00078 << " Name = " << Name() << endl
00079 << " Number of sections = " << mNumSect
00080 << ", Number of vessels = " << mNumVes << endl
00081 << " Random seed = " << mRandomSeed << endl
00082 << " Transhipment = " << mTranshipment
00083 << ", Penalty = " << mPenalty << endl << endl;
00084
00085 for (int i = 1; i <= mNumVes; i++)
00086 if (aDetail > 0)
00087 mVes[i].Print(aWidth, aDetail);
00088 else
00089 cout << "ves " << setw(4) << i
00090 << " in sect " << setw(2) << mVes[i].Section() << endl;
00091
00092 for (int k = 1; k <= mNumSect; k++)
00093 if (aDetail > 0)
00094 mSect[k].Print(aWidth, aDetail);
00095 else
00096 {
00097 cout << "sect " << setw(2) << k << " with vessels: " << endl;
00098 int i;
00099 const set<int>& V = mSect[k].Vessels();
00100 forall(i, V)
00101 {
00102 cout << i << " ";
00103 }
00104 cout << endl;
00105 }
00106 }
00107
00108
00109
00110
00111
00112
00113
00114 void BAPTVPartitioner::Solve()
00115 {
00116
00117 GenerateInitialSolution();
00118 CalcInitialObjVal();
00119
00120 gettimeofday(&mEndTime, NULL);
00121
00122 PrintSummary();
00123 WriteSolutionFile();
00124 UpdatePackage();
00125 }
00126
00127
00128 void BAPTVPartitioner::PrintSummary() const
00129 {
00130 cout << mPackage.ProjectFilename() << " --- "
00131 << mNumVes << " vessels, " << mNumSect << " sections" << endl
00132 << "Transhipment = " << mTranshipment << endl
00133 << "Penalty = " << mPenalty << endl
00134 << "Obj Value = " << CalcObjVal() << endl
00135 << "Time taken (sec) = "
00136 << (mEndTime.tv_sec - mStartTime.tv_sec) +
00137 (mEndTime.tv_usec - mStartTime.tv_usec) / 1000000.0
00138 << endl
00139 << endl;
00140 }
00141
00142
00143
00144 void BAPTVPartitioner::InitSolution()
00145 {
00146
00147 mTranshipment = 0;
00148 mPenalty = 0;
00149 mUnallocVes.clear();
00150 for (int i = 1; i <= mNumVes; i++)
00151 {
00152 mVes[i].Section(UNASSIGNED);
00153 mUnallocVes.insert(i);
00154 }
00155
00156 ResetVesselDestinations();
00157 }
00158
00159 void BAPTVPartitioner::ResetVesselDestinations()
00160 {
00161
00162 for (int i = 1; i <= mNumVes; i++)
00163 for (int k = 1; k <= mNumSect; k++)
00164 if (k != mVes[i].Section())
00165 mVes[i].AddDestination(k);
00166 }
00167
00168
00169 void BAPTVPartitioner::CalcInitialObjVal()
00170 {
00171 ComputeObjVal(mTranshipment, mPenalty);
00172 }
00173
00174
00175 void BAPTVPartitioner::ComputeObjVal(unsigned long& aTrans,
00176 unsigned long& aPenalty) const
00177 {
00178 aTrans = aPenalty = 0;
00179
00180 for (int v1 = 1; v1 <= mNumVes; v1++)
00181 {
00182 const int& s1 = mVes[v1].Section();
00183 const set<int>& neighbours = mVes[v1].Neighbours();
00184 int v2;
00185
00186
00187 forall(v2, neighbours)
00188 {
00189 if (v2 < v1) continue;
00190
00191 const int& s2 = mVes[v2].Section();
00192
00193 if (s1 == UNASSIGNED || s2 == UNASSIGNED)
00194 aPenalty += TotalFlow(v1, v2) * LONGDISTANCE;
00195 else
00196 {
00197 aTrans += TotalFlow(v1, v2) * D(s1, s2);
00198
00199
00200
00201
00202
00203 }
00204 }
00205
00206
00207 if (s1 == UNASSIGNED)
00208 aPenalty += (mVes[v1].Import() + mVes[v1].Export()) * LONGDISTANCE;
00209 else
00210 {
00211 aTrans += (mVes[v1].Import() + mVes[v1].Export()) * D(s1, 0);
00212
00213
00214
00215
00216
00217
00218 }
00219 }
00220 }
00221
00222
00223 unsigned long BAPTVPartitioner::CalcObjVal() const
00224 {
00225 unsigned long ObjVal = mTranshipment + mPenalty;
00226
00227
00228 assert(ObjVal >= mTranshipment);
00229 assert(ObjVal >= mPenalty);
00230
00231 return ObjVal;
00232 }
00233
00234 unsigned int BAPTVPartitioner::TotalFlow(const int& v1, const int& v2) const
00235 {
00236 return (unsigned int) (mTrans(v1, v2) + mTrans(v2, v1));
00237 }
00238
00239 unsigned int BAPTVPartitioner::TotalFlow(const TVVessel& v1, const TVVessel& v2) const
00240 {
00241 return (unsigned int) (mTrans(v1.ID(), v2.ID()) + mTrans(v2.ID(), v1.ID()));
00242 }
00243
00244 unsigned int BAPTVPartitioner::D(const int& s1, const int& s2) const
00245 {
00246 if (s1 >= 0 && s2 >= 0)
00247 return (unsigned int) mDist(s1, s2);
00248 else
00249 return LONGDISTANCE;
00250 }
00251
00252 unsigned int BAPTVPartitioner::D(const TVSection& s1, const TVSection& s2) const
00253 {
00254 if (s1.ID() >= 0 && s2.ID() >= 0)
00255 return (unsigned int) mDist(s1.ID(), s2.ID());
00256 else
00257 return LONGDISTANCE;
00258 }
00259
00260
00261 void BAPTVPartitioner::UpdatePackage() const
00262 {
00263 for (int i = 1; i <= mNumVes; i++)
00264 mPackage.SectionAssignedTo(i, mVes[i].Section());
00265
00266 mPackage.TranshipmentCost(mTranshipment);
00267
00268
00269 }
00270
00271
00272 void BAPTVPartitioner::ReadParameterFile()
00273 {
00274 string paramFile = mPackage.ParamFilename();
00275 char buf[255];
00276 string token, mode = "nil";
00277 ifstream ParamFile(paramFile);
00278
00279 if (!ParamFile)
00280 {
00281 cerr << "Cannot open parameter file: " << paramFile << endl;
00282 return;
00283 }
00284
00285 while (!ParamFile.eof())
00286 {
00287 ParamFile.getline(buf,80);
00288
00289 #ifdef _DEBUG
00290 cout << "tokenizing: " << buf << endl;
00291 #endif
00292
00293 for (int i = 0; i < 80; i++)
00294 if (13 == (int) buf[i])
00295 buf[i] = ' ';
00296
00297 if (buf[0] == ' ' || buf[0] == 0)
00298 continue;
00299
00300 token = strtok(buf, " ");
00301
00302 #ifdef _DEBUG
00303 cout << "token = " << token << endl;
00304 #endif
00305
00306 if (token.length() == 0)
00307 continue;
00308 if (token == "#")
00309 continue;
00310 if (token[0] == '_')
00311 mode = token;
00312 else
00313 {
00314 if (mode == "_RANDOM_SEED")
00315 {
00316 mRandomSeed = atoi(token);
00317 mRandom.set_seed(mRandomSeed);
00318 }
00319 else if (mode == "_PRINT_SECTIONS")
00320 {
00321 mPrintSections = atoi(token);
00322 }
00323 else if (mode == "_PRINT_VESSELS")
00324 {
00325 mPrintVessels = atoi(token);
00326 }
00327 else if (mode == "_RUNTIME_ANALYZER")
00328 {
00329 mRuntimeAnalyzer = atoi(token);
00330 }
00331 else if (mode == "_SUMMARY")
00332 {
00333 mSummary = atoi(token);
00334 }
00335
00336 }
00337 }
00338 }
00339
00340
00341 void BAPTVPartitioner::WriteSolutionFile() const
00342 {
00343 string solutionFile = mPackage.PartitioningFilename(),
00344 paramFile = mPackage.ParamFilename();
00345
00346 ofstream SolFile(solutionFile);
00347
00348 if (!SolFile)
00349 {
00350 cerr << "Cannot create solution file: " << solutionFile << endl;
00351 return;
00352 }
00353
00354
00355
00356 SolFile << "#" << endl
00357 << "# Solution File created by BAPTVPartitioner" << endl
00358 << "# Date = " << Date()
00359 << "# Parameter File = " << paramFile << endl
00360 << "#" << endl << endl;
00361
00362 SolFile << "_NUM_UNALLOCATED" << endl
00363 << mUnallocVes.size() << endl << endl;
00364
00365
00366 const int V = mNumVes;
00367
00368
00369 SolFile.setf(ios::fixed);
00370 SolFile << "_NUM_VESSELS" << endl
00371 << V + 1 << endl
00372 << endl
00373 << "_OBJECTIVE_VALUE" << endl
00374 << setprecision(2) << mTranshipment + mPenalty << endl
00375 << endl
00376 << "_TRANSHIPMENT_VALUE" << endl
00377 << setprecision(2) << mTranshipment << endl
00378 << endl
00379 << "_PENALTY_VALUE" << endl
00380 << setprecision(2) << mPenalty << endl
00381 << endl
00382 << "_TIME_TAKEN" << endl
00383 << setprecision(6)
00384 << (mEndTime.tv_sec - mStartTime.tv_sec) +
00385 (mEndTime.tv_usec - mStartTime.tv_usec) / 1000000.0
00386 << endl
00387 << endl;
00388 SolFile.setf(ios::fixed, ios::floatfield);
00389
00390
00391 array<int> Arrivals = mPackage.Arrivals(),
00392 Departures = mPackage.Departures();
00393
00394 SolFile << "# Final Allocation Solution" << endl
00395 << "# <ves#> <sect> <wharf> <berth time> <departure time>"
00396 << endl << endl
00397 << "_ALLOCATION" << endl;
00398
00399 SolFile << "0 0 0 0 0" << endl;
00400
00401 for (int i = 1; i <= V; i++)
00402 if (mVes[i].Section() > 0)
00403 SolFile << i << " " << mVes[i].Section() << " " << -1
00404 << " " << Arrivals[i] << " " << Departures[i]
00405 << endl;
00406
00407
00408 if (mUnallocVes.size() > 0)
00409 {
00410 SolFile << endl << "_UNALLOCATED_VESSELS" << endl;
00411
00412 for (int i = 1; i <= V; i++)
00413 if (mVes[i].Section() < 0)
00414 SolFile << i << " " << -1 << " " << -1
00415 << " " << Arrivals[i] << " " << Departures[i]
00416 << endl;
00417 }
00418
00419 SolFile << endl << endl;
00420
00421 SolFile.close();
00422 }
00423
00424
00425 void BAPTVPartitioner::WriteTraceFile(string aStr) const
00426 {
00427 ofstream TraceFile(mTraceFile, ios::app);
00428 TraceFile << aStr << endl;
00429 TraceFile.close();
00430 }
00431
00432 void BAPTVPartitioner::WriteTraceFile(long aLong) const
00433 {
00434 ofstream TraceFile(mTraceFile, ios::app);
00435 TraceFile << aLong << endl;
00436 TraceFile.close();
00437 }
00438
00439 void BAPTVPartitioner::WriteTraceFile(long double aDouble) const
00440 {
00441 ofstream TraceFile(mTraceFile, ios::app);
00442 TraceFile.setf(ios::fixed);
00443 TraceFile << setprecision(2) << aDouble << endl;
00444 TraceFile.close();
00445 }
00446
00447
00448 string BAPTVPartitioner::Date() const
00449 {
00450
00451
00452
00453 struct tm *TimePtr;
00454 time_t Time;
00455
00456 time(&Time);
00457 TimePtr = localtime(&Time);
00458
00459 return string(asctime(TimePtr));
00460 }
00461
00462
00463
00464
00465
00466 void BAPTVPartitioner::GenerateInitialSolution()
00467 {
00468 InitSolution();
00469 GenSolnRandom();
00470 }
00471
00472
00473
00474
00475
00476
00477 void BAPTVPartitioner::GenSolnRandom()
00478 {
00479
00480 array<int> V(1, mNumVes);
00481
00482 for (int i = 1; i <= mNumVes; i++)
00483 V[i] = i;
00484
00485
00486 int i, VesselsLeft = mNumVes;
00487
00488 while (VesselsLeft > 0)
00489 {
00490 i = mRandom(1, VesselsLeft);
00491 int vIndex = V[i];
00492 TVVessel& v = mVes[vIndex];
00493 AssignVesselToRandomSection(v);
00494
00495 V[i] = V[VesselsLeft];
00496 VesselsLeft--;
00497 }
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 void BAPTVPartitioner::AssignVesselToRandomSection(TVVessel& v)
00509 {
00510
00511 set<int> sectSet = v.Destinations();
00512 array<int> S(1, sectSet.size());
00513 int i = 1, k;
00514
00515 while (!sectSet.empty())
00516 {
00517 k = sectSet.choose();
00518 sectSet.del(k);
00519 S[i++] = k;
00520 }
00521
00522
00523 int SectionsLeft = S.size();
00524
00525 while (SectionsLeft > 0 && v.Section() == UNASSIGNED)
00526 {
00527 i = mRandom(1, SectionsLeft);
00528 int k = S[i];
00529
00530 if (mSect[k].CanAccommodate(v))
00531 Assign(v, mSect[k]);
00532 else
00533 S[i--] = S[SectionsLeft--];
00534 }
00535 }
00536
00537
00538 void BAPTVPartitioner::Assign(TVVessel& v, TVSection& s)
00539 {
00540 v.Section(s.ID());
00541 v.RemoveDestination(s.ID());
00542 s.Add(v);
00543 mUnallocVes.del(v.ID());
00544 }
00545
00546