00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <GlobalNodeList.h>
00025 #include <PeerInfo.h>
00026 #include <RpcMacros.h>
00027 #include <NeighborCache.h>
00028 #include <GlobalNodeListAccess.h>
00029 #include <Landmark.h>
00030 #include <UnderlayConfigurator.h>
00031 #include <SimpleNodeEntry.h>
00032 #include <SimpleInfo.h>
00033 #include <CoordBasedRoutingAccess.h>
00034 #include <GlobalStatistics.h>
00035
00036 #include <Nps_m.h>
00037
00038 #include <Nps.h>
00039
00040
00041 void Nps::init(NeighborCache* neighborCache)
00042 {
00043 this->neighborCache = neighborCache;
00044 overlay = neighborCache->overlay;
00045
00046 npsMaxLayer = neighborCache->par("npsMaxLayer");
00047 npsDimensions = neighborCache->par("npsDimensions");
00048 landmarkTimeout = neighborCache->par("landmarkTimeout");
00049
00050 GnpNpsCoordsInfo::setDimension(npsDimensions);
00051 ownCoords = new GnpNpsCoordsInfo();
00052
00053 receivedCalls = 0;
00054 pendingRequests = 0;
00055 coordCalcRuns = neighborCache->par("npsCoordCalcRuns");
00056
00057 WATCH(*ownCoords);
00058 WATCH_VECTOR(landmarkSet);
00059
00060 coordBasedRouting = CoordBasedRoutingAccess().get();
00061 globalNodeList = GlobalNodeListAccess().get();
00062
00063 if (neighborCache->getParentModule()->getModuleByRelativePath("tier1")
00064 ->getModuleByRelativePath("landmark") == NULL) {
00065 landmarkTimer = new cMessage("landmarkTimer");
00066 neighborCache->scheduleAt(simTime() + landmarkTimeout, landmarkTimer);
00067 } else {
00068
00069 ownCoords->setLayer(0);
00070 }
00071 }
00072
00073 void Nps::handleTimerEvent(cMessage* msg)
00074 {
00075
00076 if (msg == landmarkTimer) {
00077 if (enoughLandmarks()) {
00078 delete msg;
00079
00080 sendCoordRequests();
00081 } else {
00082 neighborCache->scheduleAt(simTime() + landmarkTimeout, msg);
00083 }
00084 }
00085 }
00086
00087 void Nps::handleRpcResponse(BaseResponseMessage* msg,
00088 cPolymorphic* context,
00089 int rpcId, simtime_t rtt)
00090 {
00091
00092 RPC_SWITCH_START( msg );
00093 RPC_ON_RESPONSE( CoordsReq ) {
00094 coordsReqRpcResponse(_CoordsReqResponse, context, rpcId, rtt);
00095 }
00096 #ifdef EXTJOIN_DISCOVERY
00097 RPC_ON_RESPONSE( RttToNode ) {
00098 rttToNodeRpcResponse(_RttToNodeResponse, context, rpcId, rtt);
00099 }
00100 #endif
00101 RPC_SWITCH_END( );
00102
00103 return;
00104 }
00105
00106 void Nps::handleRpcTimeout(BaseCallMessage* msg,
00107 const TransportAddress& dest,
00108 cPolymorphic* context, int rpcId,
00109 const OverlayKey& destKey)
00110 {
00111 RPC_SWITCH_START( msg ) {
00112
00113 RPC_ON_CALL( CoordsReq ) {
00114 if (true) {
00115 #ifdef EXTJOIN_DISCOVERY
00116 if (getPendingRttsReq(dest) == -1) {
00117 RttToNodeCall* call = getNodeMessage(dest);
00118
00119 RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00120 rttRes->setPingedNode(dest);
00121 rttRes->setRttToNode(0);
00122 std::vector<double> tempOwnCoords;
00123 tempOwnCoords = getOwnCoordinates();
00124 rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00125 for (uint i = 0; i < tempOwnCoords.size(); i++) {
00126 rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00127 }
00128 sendRpcResponse(call, rttRes);
00129 deleteNodeMeasurement(dest);
00130 } else {
00131 #endif
00132 updateNodeMeasurement(dest, -1);
00133 #ifdef EXTJOIN_DISCOVERY
00134 }
00135 #endif
00136
00137 } else {
00138 pendingRequests--;
00139 }
00140 }
00141 #ifdef EXTJOIN_DISCOVERY
00142 RPC_ON_CALL( RttToNode ) {
00143 updateNodeMeasurement(dest, -1);
00144 }
00145 #endif
00146 }
00147 RPC_SWITCH_END( )
00148 }
00149
00150 bool Nps::handleRpcCall(BaseCallMessage* msg)
00151 {
00152 RPC_SWITCH_START( msg );
00153 RPC_DELEGATE( CoordsReq, coordsReqRpc );
00154
00155 RPC_SWITCH_END( );
00156
00157 return RPC_HANDLED;
00158 }
00159
00160 void Nps::coordsReqRpc(CoordsReqCall* msg)
00161 {
00162 receivedCalls++;
00163 CoordsReqResponse* coordResp = new CoordsReqResponse("CoordsReqResp");
00164 coordResp->setLayer(getOwnLayer());
00165 coordResp->setNcsInfoArraySize(npsDimensions + 1);
00166
00167
00168
00169
00170 const std::vector<double>& ownCoordinates = getOwnCoordinates();
00171
00172 uint8_t i;
00173 for (i = 0; i < ownCoordinates.size(); ++i) {
00174 coordResp->setNcsInfo(i, ownCoordinates[i]);
00175 }
00176 coordResp->setNcsInfo(i, getOwnLayer());
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 coordResp->setBitLength(COORDSREQRESPONSE_L(coordResp));
00193 neighborCache->sendRpcResponse(msg, coordResp);
00194 }
00195
00196 #ifdef EXTJOIN_DISCOVERY
00197 void Nps::rttToNodeRpc(RttToNodeCall* msg)
00198 {
00199 incReceivedCalls();
00200 TransportAddress dest = msg->getNodeToPing();
00201
00202 setNodeMessage(dest, msg);
00203 sendCoordsReqCall(dest, -1);
00204 }
00205 #endif
00206
00207 void Nps::coordsReqRpcResponse(CoordsReqResponse* response,
00208 cPolymorphic* context, int rpcId, simtime_t rtt)
00209 {
00210 pendingRequests--;
00211 NodeHandle& srcNode = response->getSrcNode();
00212
00213 std::vector<double> tempCoords;
00214 for (uint8_t i = 0; i < response->getNcsInfoArraySize(); i++) {
00215 tempCoords.push_back(response->getNcsInfo(i));
00216 }
00217 GnpNpsCoordsInfo* coordsInfo =
00218 static_cast<GnpNpsCoordsInfo*>(createNcsInfo(tempCoords));
00219
00220 EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00221 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n received landmark coords: "
00222 << tempCoords[0];
00223
00224 for (uint8_t i = 1; i < npsDimensions; i++) {
00225 EV << ", " << tempCoords[i];
00226 }
00227 EV << " (rtt = " << rtt << ")" << endl;
00228
00229 #ifdef EXTJOIN_DISCOVERY
00230 if (doingDiscovery()) {
00231
00232 if ((isEntry(srcNode) && rtt < getNodeRtt(srcNode))
00233 || (isEntry(srcNode) && getNodeRtt(srcNode) < 0) ) {
00234 updateNode(srcNode, rtt, tempCoords, 0);
00235 } else if (!(isEntry(srcNode))) {
00236 updateNode(srcNode, rtt, tempCoords, 0);
00237 } else {
00238 updateNode(srcNode, getNodeRtt(srcNode), tempCoords, 0);
00239 }
00240 setNodeLayer(srcNode, tempLayer);
00241 }
00242 else if (doingNodeMeasurement()) {
00243 if (getPendingRttsReq(srcNode) == -1) {
00244 updateNode(srcNode, rtt, tempCoords, 0);
00245 setNodeLayer(srcNode, tempLayer);
00246 RttToNodeCall* prevCall = getNodeMessage(srcNode);
00247
00248 RttToNodeResponse* rttRes = new RttToNodeResponse("RttToNodeXRes");
00249 rttRes->setPingedNode(srcNode);
00250 rttRes->setRttToNode(rtt);
00251 std::vector<double> tempOwnCoords;
00252 tempOwnCoords = getOwnCoordinates();
00253 rttRes->setOwnCoordinatesArraySize(tempOwnCoords.size());
00254 for (uint i = 0; i < tempOwnCoords.size(); i++) {
00255 rttRes->setOwnCoordinates(i, tempOwnCoords[i]);
00256 }
00257
00258 sendRpcResponse(prevCall, rttRes);
00259 deleteNodeMeasurement(srcNode);
00260 } else {
00261 updateNode(srcNode, rtt, tempCoords, 0);
00262 setNodeLayer(srcNode, tempLayer);
00263 if (checkCoordinates(getOwnCoordinates(), tempCoords, rtt)) {
00264 updateNodeMeasurement(srcNode, -1, 0, 1);
00265 } else {
00266 updateNodeMeasurement(srcNode, -1, 0, 0);
00267 }
00268 }
00269 }
00270 else
00271 #endif
00272 if (pendingRequests == 0) {
00273
00274 neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00275 coordsInfo);
00276
00277 std::vector<LandmarkDataEntry> probedLandmarks;
00278 if (getLandmarkSetSize() < npsDimensions + 1) {
00279 setLandmarkSet(npsDimensions + 1, npsMaxLayer, &landmarkSet);
00280 }
00281
00282 for (std::vector<TransportAddress>::iterator it = landmarkSet.begin();
00283 it != landmarkSet.end(); ++it) {
00284 const GnpNpsCoordsInfo* tempInfo =
00285 dynamic_cast<const GnpNpsCoordsInfo*>(neighborCache->getNodeCoordsInfo(*it));
00286
00287 assert(tempInfo);
00288
00289 LandmarkDataEntry temp;
00290 temp.coordinates.resize(tempInfo->getDimension());
00291 temp.rtt = neighborCache->getNodeRtt(*it).first;
00292 temp.layer = tempInfo->getLayer();
00293 for (uint8_t i = 0; i < tempInfo->getDimension(); ++i) {
00294 temp.coordinates[i] = tempInfo->getCoords(i);
00295 }
00296 temp.ip = NULL;
00297
00298 probedLandmarks.push_back(temp);
00299 }
00300 assert(probedLandmarks.size() > 0);
00301
00302 computeOwnCoordinates(probedLandmarks);
00303 computeOwnLayer(probedLandmarks);
00304
00305 std::vector<double> coords = getOwnCoordinates();
00306 EV << "[Nps::coordsReqRpcResponse() @ " << neighborCache->thisNode.getAddress()
00307 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]\n setting own coords: "
00308 << coords[0];
00309 for (uint8_t i = 1; i < npsDimensions; i++) {
00310 EV << ", " << coords[i];
00311 }
00312 EV << endl;
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 SimpleNodeEntry* entry =
00327 dynamic_cast<SimpleInfo*>(globalNodeList->
00328 getPeerInfo(neighborCache->thisNode.getAddress()))->getEntry();
00329
00330 double error = 0;
00331 for (uint8_t i = 1; i < entry->getDim(); i++) {
00332 error += pow(coords[i] - entry->getCoords(i), 2);
00333 }
00334 error = sqrt(error);
00335
00336 neighborCache->globalStatistics
00337 ->addStdDev("NPS: Coordinate difference", error);
00338
00339 neighborCache->neighborCache.clear();
00340 neighborCache->neighborCacheExpireMap.clear();
00341
00342 neighborCache->getParentModule()
00343 ->bubble("GNP/NPS coordinates calculated -> JOIN overlay!");
00344
00345 if (coordBasedRouting) {
00346 int bitsPerDigit = neighborCache->overlay->getBitsPerDigit();
00347 neighborCache->thisNode.setKey(
00348 coordBasedRouting->getNodeId(coords, bitsPerDigit,
00349 OverlayKey::getLength()));
00350
00351 EV << "[Nps::coordsReqRpcResponse() @ "
00352 << neighborCache->thisNode.getAddress()
00353 << " (" << neighborCache->thisNode.getKey().toString(16) << ")]"
00354 << "\n -> nodeID ( 2): "
00355 << neighborCache->thisNode.getKey().toString(2)
00356 << "\n -> nodeID (16): "
00357 << neighborCache->thisNode.getKey().toString(16) << endl;
00358
00359
00360 neighborCache->overlay->join(neighborCache->thisNode.getKey());
00361 } else {
00362
00363 neighborCache->overlay->join();
00364 }
00365 } else {
00366 neighborCache->updateNode(srcNode, rtt, NodeHandle::UNSPECIFIED_NODE,
00367 coordsInfo);
00368 }
00369 }
00370
00371 #ifdef EXTJOIN_DISCOVERY
00372 void Nps::rttToNodeRpcResponse(RttToNodeResponse* response,
00373 cPolymorphic* context, int rpcId, simtime_t rtt)
00374 {
00375 uint dim = coordBasedRouting->getXmlDimensions();
00376 TransportAddress nodeToCheck = response->getPingedNode();
00377 std::vector<double> tempCoords;
00378 tempCoords.resize(dim);
00379 for (uint i = 0; i < dim; i++) {
00380 tempCoords[i] = response->getOwnCoordinates(i);
00381 }
00382 if (checkCoordinates(tempCoords, getNodeCoords(nodeToCheck), response->getRttToNode())) {
00383 updateNodeMeasurement(nodeToCheck, -1, 0, 1);
00384 } else {
00385 updateNodeMeasurement(nodeToCheck, -1, 0, 0);
00386 }
00387 delete context;
00388 }
00389 #endif
00390
00391
00392 bool Nps::setLandmarkSet(uint8_t howManyLM, uint8_t maxLayer,
00393 std::vector<TransportAddress>* landmarkSet)
00394 {
00395 landmarkSet->clear();
00396 NeighborCache::NeighborCacheIterator it;
00397 uint availableLM = 0;
00398 TransportAddress landmark;
00399 for(it = neighborCache->neighborCache.begin(); it != neighborCache->neighborCache.end(); it++ ) {
00400 if (dynamic_cast<GnpNpsCoordsInfo*>(it->second.coordsInfo) &&
00401 static_cast<GnpNpsCoordsInfo*>(it->second.coordsInfo)->getLayer()
00402 < maxLayer) {
00403 landmark.setAddress(it->first.getAddress());
00404 landmark.setPort(it->second.nodeRef.getPort());
00405 landmarkSet->push_back(landmark);
00406 availableLM++;
00407 }
00408 }
00409 if (availableLM < howManyLM) {
00410 return false;
00411 } else {
00412 uint i = availableLM;
00413 while (i > howManyLM) {
00414 uint randomNumber = (intuniform(0, landmarkSet->size()));
00415 landmarkSet->erase(landmarkSet->begin() + randomNumber);
00416 i--;
00417 }
00418 return true;
00419 }
00420 }
00421
00422 void Nps::sendCoordRequests()
00423 {
00424 std::vector <TransportAddress> landmarks;
00425 landmarks = getLandmarks(npsDimensions + 1);
00426
00427 simtime_t timeout = -1;
00428
00429 if (landmarks.size() > 0) {
00430 for (size_t i = 0; i < landmarks.size(); i++) {
00431 const TransportAddress& tolm = landmarks[i];
00432 sendCoordsReqCall(tolm, timeout);
00433 }
00434 setLandmarkSet(npsDimensions + 1, npsMaxLayer, &landmarkSet);
00435 }
00436 }
00437
00438 void Nps::sendCoordsReqCall(const TransportAddress& dest,
00439 simtime_t timeout)
00440 {
00441 CoordsReqCall* coordReq = new CoordsReqCall("CoordsReq");
00442 coordReq->setBitLength(COORDSREQCALL_L(coordReq));
00443 neighborCache->sendRouteRpcCall(neighborCache->getThisCompType(), dest,
00444 coordReq, NULL, NO_OVERLAY_ROUTING,
00445 timeout, 0, -1, this);
00446 pendingRequests++;
00447 }
00448
00449 void Nps::computeOwnLayer(const std::vector<LandmarkDataEntry>& landmarks)
00450 {
00451 int8_t computedLayer = getOwnLayer();
00452 for (uint i = 0; i < landmarks.size(); i++) {
00453 if (computedLayer <= landmarks[i].layer) {
00454 computedLayer = landmarks[i].layer + 1;
00455 }
00456 }
00457 setOwnLayer(computedLayer);
00458 }
00459
00460 void Nps::setOwnLayer(int8_t layer)
00461 {
00462 ownCoords->setLayer(layer);
00463
00464
00465 PeerInfo* thisInfo = globalNodeList->getPeerInfo(neighborCache->getThisNode());
00466 thisInfo->setNpsLayer(layer);
00467
00468
00469 if (layer > 0) globalNodeList->refreshEntry(neighborCache->overlay->getThisNode());
00470 if (layer < npsMaxLayer) {
00471 globalNodeList->incLandmarkPeerSize();
00472 globalNodeList->incLandmarkPeerSizePerType(thisInfo->getTypeID());
00473 }
00474 }
00475
00476 #ifdef EXTJOIN_DISCOVERY
00477 bool Nps::checkCoordinates(std::vector<double> coordsOK, std::vector<double> coordsToCheck, simtime_t dist)
00478 {
00479 simtime_t predDist = 0.0;
00480
00481 for (uint i = 0; i < coordsOK.size(); i++) {
00482 predDist += pow(coordsOK[i] - coordsToCheck[i], 2);
00483 }
00484 simtime_t predDistLow = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 - 0.3) / 1000;
00485 simtime_t predDistHigh = sqrt(SIMTIME_DBL(predDist)) * 2 * (1 + 0.3) / 1000;
00486 if (dist > predDistLow && dist < predDistHigh) {
00487 return true;
00488 } else {
00489
00490 return false;
00491 }
00492 }
00493 #endif
00494
00495 void Nps::computeOwnCoordinates(const std::vector<LandmarkDataEntry>& landmarks)
00496 {
00497 CoordCalcFunction coordcalcf(landmarks);
00498
00499 Vec_DP initCoordinates(npsDimensions);
00500 Vec_DP bestCoordinates(npsDimensions);
00501 std::vector<double> computedCoordinatesStdVector(npsDimensions);
00502
00503 double bestval;
00504 double resval;
00505
00506 for (uint runs = 0; runs < coordCalcRuns; runs++) {
00507
00508 for (uint i = 0; i < npsDimensions; i++) {
00509 initCoordinates[i] = uniform(-100, 100);
00510 }
00511
00512
00513
00514 resval = CoordCalcFunction::simplex_min(&coordcalcf, initCoordinates);
00515 if (runs == 0 || (runs > 0 && resval < bestval) ) {
00516 bestval = resval;
00517 bestCoordinates = initCoordinates;
00518 }
00519 }
00520
00521 for (uint i = 0; i < npsDimensions; i++) {
00522 computedCoordinatesStdVector[i] = bestCoordinates[i];
00523 }
00524
00525 setOwnCoordinates(computedCoordinatesStdVector);
00526 }
00527
00528 std::vector<TransportAddress> Nps::getLandmarks(uint8_t howmany)
00529 {
00530 std::vector<TransportAddress> returnPool;
00531
00532 if (howmany > globalNodeList->getLandmarkPeerSize()) {
00533 throw cRuntimeError("Not enough landmarks available in network!");
00534 }
00535
00536 while (returnPool.size() < howmany) {
00537 TransportAddress* lm = globalNodeList->getRandomAliveNode();
00538 PeerInfo* lmInfo = globalNodeList->getPeerInfo(lm->getAddress());
00539 if (lmInfo->getNpsLayer() >= 0 &&
00540 lmInfo->getNpsLayer() < npsMaxLayer) {
00541
00542 bool alreadyin = false;
00543 for (uint8_t i = 0; i < returnPool.size(); i++) {
00544 if (returnPool[i] == *lm)
00545 alreadyin = true;
00546 }
00547 if (alreadyin == false) {
00548 returnPool.push_back(*lm);
00549 }
00550 }
00551 }
00552 return returnPool;
00553 }
00554
00555 bool Nps::enoughLandmarks()
00556 {
00557 return (globalNodeList->getLandmarkPeerSize() > npsDimensions);
00558 }
00559
00560
00561 Prox Nps::getCoordinateBasedProx(const AbstractNcsNodeInfo& abstractInfo) const
00562 {
00563 return ownCoords->getDistance(abstractInfo);
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 }
00584
00585 void Nps::updateNodeMeasurement(const TransportAddress& node,
00586 uint8_t pending,
00587 uint8_t sent,
00588 uint8_t passed)
00589 {
00590 bool alreadySet = false;
00591 for(uint i = 0; i < nodeMeasurements.size(); i++) {
00592 if (nodeMeasurements[i].measuredNode == node && sent == 0) {
00593 nodeMeasurements[i].rttsPending += pending;
00594 nodeMeasurements[i].rttsSent += sent;
00595 nodeMeasurements[i].coordsPassed += passed;
00596 alreadySet = true;
00597 i = nodeMeasurements.size();
00598 } else if (nodeMeasurements[i].measuredNode == node) {
00599 nodeMeasurements[i].rttsPending = pending;
00600 nodeMeasurements[i].rttsSent = sent;
00601 nodeMeasurements[i].coordsPassed = passed;
00602 alreadySet = true;
00603 i = nodeMeasurements.size();
00604 }
00605 }
00606 if (!alreadySet) {
00607 RttMeasurement newNode;
00608 newNode.measuredNode = node;
00609 newNode.rttsPending = pending;
00610 newNode.rttsSent = sent;
00611 newNode.coordsPassed = passed;
00612 nodeMeasurements.push_back(newNode);
00613 }
00614 }
00615
00616 void Nps::deleteNodeMeasurement(const TransportAddress& node)
00617 {
00618 for(uint i = 0; i < nodeMeasurements.size(); i++) {
00619 if (nodeMeasurements[i].measuredNode == node) {
00620 #ifdef EXTJOIN_DISCOVERY
00621 delete nodeMeasurements[i].message;
00622 #endif
00623 nodeMeasurements.erase(nodeMeasurements.begin()+i);
00624 i--;
00625 }
00626 }
00627 if (nodeMeasurements.size() == 0) {
00628
00629 }
00630 }
00631
00632
00633 AbstractNcsNodeInfo* Nps::createNcsInfo(const std::vector<double>& coords) const
00634 {
00635 assert(coords.size() > 1);
00636 GnpNpsCoordsInfo* info = new GnpNpsCoordsInfo();
00637
00638 uint8_t i;
00639 for (i = 0; i < coords.size() - 1; ++i) {
00640 info->setCoords(i, coords[i]);
00641 }
00642 info->setLayer(coords[i]);
00643
00644 return info;
00645 }
00646
00647
00648 double CoordCalcFunction::simplex_min(CoordCalcFunction *functionObject,
00649 Vec_DP& init)
00650 {
00651 double accf = 0.0000001;
00652 double accx = 0.0000001;
00653 uint32_t nmax = 30001;
00654 uint8_t dim = init.size();
00655 Simplex spx(dim);
00656
00657 int ihi;
00658 Vec_DP phi(dim);
00659 double vhi;
00660 double vre;
00661 double vlo, diff;
00662 uint32_t count;
00663
00664
00665 Vec_DP tmp(dim);
00666 spx.functionObject = functionObject;
00667 spx[0] = init;
00668 for (uint8_t i = 0; i < dim; i++) {
00669 tmp[i] = 1;
00670 spx[i+1] = init + tmp;
00671 tmp[i] = 0;
00672 }
00673
00674 Vec_DP debugCoords(dim);
00675
00676 for (count = 1; count <= nmax; count++) {
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 ihi = spx.high(&vhi);
00688 phi = spx[ihi];
00689 spx.reflect();
00690 vre = functionObject->f(spx[ihi]);
00691 if (vre < functionObject->f(spx[spx.low()])) {
00692 spx[ihi] = phi;
00693 spx.reflect_exp();
00694 vre = functionObject->f(spx[ihi]);
00695 if (vre > functionObject->f(spx[spx.low()])) {
00696 spx[ihi] = phi;
00697 spx.reflect();
00698 }
00699 } else if (vre >= vhi) {
00700 spx[ihi] = phi;
00701 spx.contract();
00702 if (functionObject->f(spx[ihi]) > vhi) {
00703 spx[ihi] = phi;
00704 spx.reduce();
00705 }
00706 }
00707
00708 spx.high(&vhi);
00709 spx.low(&vlo);
00710 diff = vhi - vlo;
00711 if (diff < accf)
00712 if (spx.size() < accx)
00713 break;
00714 }
00715 init = spx[spx.low()];
00716 return vlo;
00717 }
00718
00719 double CoordCalcFunction::f(const Vec_DP& initCoordinates) const
00720 {
00721 double sum = 0;
00722 double rel_diff = 0;
00723
00724 for (uint i = 0; i < landmarks.size(); i++) {
00725
00726 double diff = SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000 -
00727 endnodeDistance(initCoordinates, landmarks[i]);
00728
00729 if (SIMTIME_DBL(landmarks[i].rtt) != 0) {
00730 rel_diff = diff / (SIMTIME_DBL(landmarks[i].rtt) / 2 * 1000);
00731 } else {
00732 opp_error("[CBR] RTT == 0. Node is landmark? This shouldn't happen.");
00733 }
00734 sum += rel_diff * rel_diff;
00735 }
00736 return sum;
00737 }
00738
00739 double CoordCalcFunction::endnodeDistance(const Vec_DP& nodeCoordinates,
00740 LandmarkDataEntry landmark) const
00741 {
00742 double sum_of_squares = 0.0;
00743 for (int i = 0; i < nodeCoordinates.size(); i++) {
00744 sum_of_squares += pow(landmark.coordinates[i] - nodeCoordinates[i], 2);
00745 }
00746 double result = sqrt(sum_of_squares);
00747 return result;
00748 }
00749