bool ResourceNode::_TrackBack(ResourceNode* node, STD_NAMESPACE::set<ResourceNode*>& trackBuffer) { if (m_isRootNode) return true; m_isDeleted = true; STD_NAMESPACE::set<ResourceNode*>::iterator iter = node->m_inputs.begin(); for (; iter != node->m_inputs.end(); iter++) { ResourceNode* i = *iter; if (i->m_isDeleted) continue; if (trackBuffer.find(i) != trackBuffer.end()) continue; trackBuffer.insert(i); if (_TrackBack(i, trackBuffer)) { m_isDeleted = false; return true; } } iter = m_outputs.begin(); for (; iter != m_outputs.end(); iter++) { ResourceNode* node = *iter; if (node->m_isDeleted) continue; node->m_inputs.erase(this); } MarkDeleted(); return false; }
GainType LKH::LKHAlg::PatchCycles(int k, GainType Gain) { Node *s1, *s2, *sStart, *sStop; GainType NewGain; int M, i; if(!CurrentCycle.get()) { CurrentCycle.reset(new int(0)); Patchwork.reset(new int(0)); RecLevel.reset(new int(0)); } FindPermutation(k,this); M = Cycles(k); if (M == 1 && Gain > 0) { MakeKOptMove(k); return Gain; } if (M == 1 || M > PatchingC || k + M > NonsequentialMoveType) return 0; if (*RecLevel == 0) *Patchwork = 0; *CurrentCycle = ShortestCycle(M, k,this); for (i = 0; i < k; i++) { if ((*cycle.get())[(*p.get())[2 * i]] != *CurrentCycle) continue; sStart = (*t.get())[(*p.get())[2 * i]]; sStop = (*t.get())[(*p.get())[2 * i + 1]]; for (s1 = sStart; s1 != sStop; s1 = s2) { s2 = SUC(s1); if (FixedOrCommon(s1, s2)) continue; if (++(*Patchwork) > Dimension) return 0; (*t.get())[2 * k + 1] = s1; (*t.get())[2 * k + 2] = s2; MarkDeleted(s1, s2); /* Find a set of gainful alternating cycles */ NewGain = PatchCyclesRec(k, 2, M, Gain + (this->*C)(s1, s2),this); UnmarkDeleted(s1, s2); if (NewGain > 0) return NewGain; } } return 0; }
LKH::LKHAlg::Node * LKH::LKHAlg::BestKOptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain) { if(!BestG2.get()) BestG2.reset(new GainType(0)); *K = Swaps == 0 ? MoveType : SubsequentMoveType; *Gain = 0; (*t.get())[1] = t1; (*t.get())[2] = t2; (*T.get())[2 * *K] = 0; *BestG2 = MINUS_INFINITY; /* * Determine (T[3],T[4], ..., T[2K]) = (t[3],t[4], ..., t[2K]) * such that * * G[2 * K] = *G0 - C(t[2],T[3]) + C(T[3],T[4]) * - C(T[4],T[5]) + C(T[5],T[6]) * ... * - C(T[2K-3],T[2K-2]) + C(T[2K-1],T[2K]) * * is maximum, and (T[2K-1],T[2K]) has not previously been included. * If during this process a legal move with *Gain > 0 is found, then * make the move and exit BestKOptMove immediately. */ MarkDeleted(t1, t2); *Gain = BestKOptMoveRec(2, *G0,this); UnmarkDeleted(t1, t2); if (*Gain <= 0 && (*T.get())[2 * *K]) { int i; memcpy(t.get() + 1, T.get() + 1, 2 * *K * sizeof(Node *)); for (i = 2; i < 2 * *K; i += 2) (*incl.get())[(*incl.get())[i] = i + 1] = i; (*incl.get())[(*incl.get())[1] = 2 * *K] = 1; MakeKOptMove(*K); for (i = 1; i < 2 * *K; i += 2) Exclude((*T.get())[i], (*T.get())[i + 1]); *G0 = *BestG2; return (*T.get())[2 * *K]; } return 0; }
void CItems::Delete(std::vector<int>& vIds, BOOL bRemove /*= FALSE*/) { std::map<int, int> setIds; for (std::vector<int>::iterator it = vIds.begin(); it != vIds.end(); ++it) { if (setIds.find(*it) == setIds.end()) { std::vector< std::pair<int, int> > v; EnumItems(*it, v); for (std::vector< std::pair<int, int> >::iterator vi = v.begin(); vi != v.end(); ++vi) { // first - id, second - is folder setIds[vi->first] = vi->second; } } } for (std::map<int, int>::iterator it = setIds.begin(); it != setIds.end(); ++it) { if (bRemove) { RemoveItem(it->first); } else { MarkDeleted(it->first); } if (it->second) // folder { CApplicationImpl::Get().UpdateViews(UNM_FOLDER_DELETED, it->first); } else { CApplicationImpl::Get().UpdateViews(UNM_ITEM_DELETED, it->first); } } }
static GainType BestKOptMoveRec(int k, GainType G0,LKH::LKHAlg *Alg) { LKH::LKHAlg::Candidate *Nt2; LKH::LKHAlg::Node *t1, *t2, *t3, *t4; GainType G1, G2, G3, Gain; int X4, i; int Breadth2 = 0; t1 = (*t.get())[1]; t2 = (*t.get())[i = 2 * k - 2]; (*incl.get())[(*incl.get())[i] = i + 1] = i; (*incl.get())[(*incl.get())[1] = i + 2] = 1; /* Choose (t2,t3) as a candidate edge emanating from t2 */ for (Nt2 = t2->CandidateSet; (t3 = Nt2->To); Nt2++) { if (t3 == t2->Pred || t3 == t2->Suc || ((G1 = G0 - Nt2->Cost) <= 0 && Alg->GainCriterionUsed && Alg->ProblemType != LKH::HCP && Alg->ProblemType != LKH::HPP) || Added(t2, t3)) continue; if (++Breadth2 > Alg->MaxBreadth) break; MarkAdded(t2, t3); (*t.get())[2 * k - 1] = t3; (*G.get())[2 * k - 2] = G1 + t3->Pi; /* Choose t4 as one of t3's two neighbors on the tour */ for (X4 = 1; X4 <= 2; X4++) { t4 = X4 == 1 ? (Alg->Reversed == (t3)->Parent->Reversed ? (t3)->Pred : (t3)->Suc) : (Alg->Reversed == (t3)->Parent->Reversed ? (t3)->Suc : (t3)->Pred); if ((Fixed(t3, t4) || Alg->IsCommonEdge(t3, t4)) || Deleted(t3, t4)) continue; (*t.get())[2 * k] = t4; G2 = G1 + (Alg->*(Alg->C))(t3, t4); G3 = MINUS_INFINITY; if (t4 != t1 && !Alg->Forbidden(t4, t1) && !Added(t4, t1) && (!Alg->c || G2 - (Alg->*(Alg->c))(t4, t1) > 0) && (G3 = G2 - (Alg->*(Alg->C))(t4, t1)) > 0 && FeasibleKOptMove(k)) { UnmarkAdded(t2, t3); Alg->MakeKOptMove(k); return G3; } if (Alg->Backtracking && !Alg->Excludable(t3, t4)) continue; MarkDeleted(t3, t4); (*G.get())[2 * k - 1] = G2 - t4->Pi; if (k < *K) { if ((Gain = BestKOptMoveRec(k + 1, G2,Alg)) > 0) { UnmarkAdded(t2, t3); UnmarkDeleted(t3, t4); return Gain; } (*incl.get())[(*incl.get())[1] = 2 * k] = 1; } if (t4 != t1 && !Alg->Forbidden(t4, t1) && k + 1 < Alg->NonsequentialMoveType && Alg->PatchingC >= 2 && Alg->PatchingA >= 1 && (Alg->Swaps == 0 || Alg->SubsequentPatching)) { if (G3 == MINUS_INFINITY) G3 = G2 - (Alg->*(Alg->C))(t4, t1); if ((Alg->PatchingCRestricted ? G3 > 0 && Alg->IsCandidate(t4, t1) : Alg->PatchingCExtended ? G3 > 0 || Alg->IsCandidate(t4, t1) : G3 > 0) && (Gain = Alg->PatchCycles(k, G3)) > 0) { UnmarkAdded(t2, t3); UnmarkDeleted(t3, t4); return Gain; } } UnmarkDeleted(t3, t4); if (k == *K && t4 != t1 && t3 != t1 && G3 <= 0 && !Added(t4, t1) && (!Alg->GainCriterionUsed || G2 - Alg->Precision >= t4->Cost)) { if (!Alg->Backtracking || Alg->Swaps > 0) { if ((G2 > *BestG2 || (G2 == *BestG2 && !Near(t3, t4) && Near((*T.get())[2 * *K - 1], (*T.get())[2 * *K]))) && Alg->Swaps < Alg->MaxSwaps && Alg->Excludable(t3, t4) && !InInputTour(t3, t4)) { if (Alg->RestrictedSearch && *K > 2 && Alg->ProblemType != LKH::HCP && Alg->ProblemType != LKH::HPP) { /* Ignore the move if the gain does not vary */ (*G.get())[0] = (*G.get())[2 * *K - 2]; (*G.get())[1] = (*G.get())[2 * *K - 1]; for (i = 2 * *K - 3; i >= 2; i--) if ((*G.get())[i] != (*G.get())[i % 2]) break; if (i < 2) continue; } if (FeasibleKOptMove(*K)) { *BestG2 = G2; memcpy(T.get() + 1, t.get() + 1, 2 * *K * sizeof(LKH::LKHAlg::Node *)); } } } else if (Alg->MaxSwaps > 0 && FeasibleKOptMove(*K)) { LKH::LKHAlg::Node *SUCt1 = (Alg->Reversed == (t1)->Parent->Reversed ? (t1)->Suc : (t1)->Pred); Alg->MakeKOptMove(*K); for (i = 1; i < 2 * k; i += 2) { Alg->Exclude((*t.get())[i], (*t.get())[i + 1]); UnmarkDeleted((*t.get())[i], (*t.get())[i + 1]); } for (i = 2; i < 2 * k; i += 2) UnmarkAdded((*t.get())[i], (*t.get())[i + 1]); memcpy(tSaved.get() + 1, t.get() + 1, 2 * k * sizeof(LKH::LKHAlg::Node *)); while ((t4 = (Alg->*(Alg->BestSubsequentMove))(t1, t4, &G2, &Gain))); if (Gain > 0) { UnmarkAdded(t2, t3); return Gain; } Alg->RestoreTour(); *K = k; memcpy(t.get() + 1, tSaved.get() + 1, 2 * *K * sizeof(LKH::LKHAlg::Node *)); for (i = 1; i < 2 * *K - 2; i += 2) MarkDeleted((*t.get())[i], (*t.get())[i + 1]); for (i = 2; i < 2 * *K; i += 2) MarkAdded((*t.get())[i], (*t.get())[i + 1]); for (i = 2; i < 2 * *K; i += 2) (*incl.get())[(*incl.get())[i] = i + 1] = i; (*incl.get())[(*incl.get())[1] = 2 * *K] = 1; if (SUCt1 != (Alg->Reversed == (t1)->Parent->Reversed ? (t1)->Suc : (t1)->Pred)) Alg->Reversed ^= 1; (*T.get())[2 * *K] = 0; } } } UnmarkAdded(t2, t3); if (t3 == t1) continue; /* Try to delete an added edge, (_,t3) or (t3,_) */ for (i = 2 * k - 4; i >= 2; i--) { if (t3 == (*t.get())[i]) { t4 = (*t.get())[i ^ 1]; if (t4 == t1 || Alg->Forbidden(t4, t1) || (Fixed(t3, t4) || Alg->IsCommonEdge(t3, t4)) || Added(t4, t1)) continue; G2 = G1 + (Alg->*(Alg->C))(t3, t4); if ((!Alg->c || G2 - (Alg->*(Alg->c))(t4, t1) > 0) && (Gain = G2 - (Alg->*(Alg->C))(t4, t1)) > 0) { (*incl.get())[(*incl.get())[i ^ 1] = 1] = i ^ 1; (*incl.get())[(*incl.get())[i] = 2 * k - 2] = i; if (FeasibleKOptMove(k - 1)) { Alg->MakeKOptMove(k - 1); return Gain; } (*incl.get())[(*incl.get())[i ^ 1] = i] = i ^ 1; } } } (*incl.get())[1] = 2 * k; (*incl.get())[2 * k - 2] = 2 * k - 1; } return 0; }
static GainType PatchCyclesRec(int k, int m, int M, GainType G0, LKH::LKHAlg *Alg) { LKH::LKHAlg::Node *s1, *s2, *s3, *s4, *s5, *s6, *S3 = 0, *S4 = 0; LKH::LKHAlg::Candidate *Ns2, *Ns4; GainType G1, G2, G3, G4, Gain, CloseUpGain, BestCloseUpGain = Alg->PatchingAExtended ? MINUS_INFINITY : 0; int X4, X6; int i, NewCycle, *cycleSaved = 0, *pSaved = 0; int Breadth2 = 0, Breadth4; s1 = (*t.get())[2 * k + 1]; s2 = (*t.get())[i = 2 * (k + m) - 2]; (*incl.get())[(*incl.get())[i] = i + 1] = i; /* Choose (s2,s3) as a candidate edge emanating from s2 */ for (Ns2 = s2->CandidateSet; (s3 = Ns2->To); Ns2++) { if (s3 == s2->Pred || s3 == s2->Suc || Added(s2, s3) || (NewCycle = Cycle(s3, k,Alg)) == *CurrentCycle) continue; if (++Breadth2 > Alg->MaxBreadth) break; MarkAdded(s2, s3); (*t.get())[2 * (k + m) - 1] = s3; G1 = G0 - Ns2->Cost; /* Choose s4 as one of s3's two neighbors on the tour */ for (X4 = 1; X4 <= 2; X4++) { s4 = X4 == 1 ? s3->Pred : s3->Suc; if ((Fixed(s3, s4) || Alg->IsCommonEdge(s3, s4)) || Deleted(s3, s4)) continue; MarkDeleted(s3, s4); (*t.get())[2 * (k + m)] = s4; G2 = G1 + (Alg->*(Alg->C))(s3, s4); if (M > 2) { if (!cycleSaved) { assert(cycleSaved = (int *) malloc(2 * k * sizeof(int))); memcpy(cycleSaved, cycle.get() + 1, 2 * k * sizeof(int)); } for (i = 1; i <= 2 * k; i++) if ((*cycle.get())[i] == NewCycle) (*cycle.get())[i] = *CurrentCycle; /* Extend the current alternating path */ if ((Gain = PatchCyclesRec(k, m + 1, M - 1, G2,Alg)) > 0) { UnmarkAdded(s2, s3); UnmarkDeleted(s3, s4); goto End_PatchCyclesRec; } memcpy(cycle.get() + 1, cycleSaved, 2 * k * sizeof(int)); if (Alg->PatchingA >= 2 && *Patchwork < Alg->Dimension && k + M < Alg->NonsequentialMoveType && !Alg->Forbidden(s4, s1) && (!Alg->PatchingARestricted || Alg->IsCandidate(s4, s1))) { GainType Bound = BestCloseUpGain >= 0 || Alg->IsCandidate(s4, s1) ? BestCloseUpGain : 0; if ((!Alg->c || G2 - (Alg->*(Alg->c))(s4, s1) > Bound) && (CloseUpGain = G2 - (Alg->*(Alg->C))(s4, s1)) > Bound) { S3 = s3; S4 = s4; BestCloseUpGain = CloseUpGain; } } } else if (!Alg->Forbidden(s4, s1) && (!Alg->c || G2 - (Alg->*(Alg->c))(s4, s1) > 0) && (Gain = G2 - (Alg->*(Alg->C))(s4, s1)) > 0) { (*incl.get())[(*incl.get())[2 * k + 1] = 2 * (k + m)] = 2 * k + 1; Alg->MakeKOptMove(k + m); UnmarkAdded(s2, s3); UnmarkDeleted(s3, s4); goto End_PatchCyclesRec; } UnmarkDeleted(s3, s4); } UnmarkAdded(s2, s3); } if (M == 2 && !Alg->PatchingCRestricted) { /* Try to patch the two cycles by a sequential 3-opt move */ (*incl.get())[(*incl.get())[2 * (k + m)] = 2 * (k + m) + 1] = 2 * (k + m); (*incl.get())[(*incl.get())[2 * k + 1] = 2 * (k + m) + 2] = 2 * k + 1; Breadth2 = 0; /* Choose (s2,s3) as a candidate edge emanating from s2 */ for (Ns2 = s2->CandidateSet; (s3 = Ns2->To); Ns2++) { if (s3 == s2->Pred || s3 == s2->Suc || Added(s2, s3)) continue; if (++Breadth2 > Alg->MaxBreadth) break; (*t.get())[2 * (k + m) - 1] = s3; G1 = G0 - Ns2->Cost; NewCycle = Cycle(s3, k,Alg); /* Choose s4 as one of s3's two neighbors on the tour */ for (X4 = 1; X4 <= 2; X4++) { s4 = X4 == 1 ? s3->Pred : s3->Suc; if ((Fixed(s3, s4) || Alg->IsCommonEdge(s3, s4)) || Deleted(s3, s4)) continue; (*t.get())[2 * (k + m)] = s4; G2 = G1 + (Alg->*(Alg->C))(s3, s4); Breadth4 = 0; /* Choose (s4,s5) as a candidate edge emanating from s4 */ for (Ns4 = s4->CandidateSet; (s5 = Ns4->To); Ns4++) { if (s5 == s4->Pred || s5 == s4->Suc || s5 == s1 || Added(s4, s5) || (NewCycle == *CurrentCycle && Cycle(s5, k,Alg) == *CurrentCycle)) continue; if (++Breadth4 > Alg->MaxBreadth) break; G3 = G2 - Ns4->Cost; /* Choose s6 as one of s5's two neighbors on the tour */ for (X6 = 1; X6 <= 2; X6++) { s6 = X6 == 1 ? s5->Pred : s5->Suc; if (s6 == s1 || Alg->Forbidden(s6, s1) || (Fixed(s5, s6) || Alg->IsCommonEdge(s5, s6)) || Deleted(s5, s6) || Added(s6, s1)) continue; G4 = G3 + (Alg->*(Alg->C))(s5, s6); if ((!Alg->c || G4 - (Alg->*(Alg->c))(s6, s1) > 0) && (Gain = G4 - (Alg->*(Alg->C))(s6, s1)) > 0) { if (!pSaved) { assert(pSaved = (int *) malloc(2 * k * sizeof(int))); memcpy(pSaved, p.get() + 1, 2 * k * sizeof(int)); } (*t.get())[2 * (k + m) + 1] = s5; (*t.get())[2 * (k + m) + 2] = s6; if (FeasibleKOptMove(k + m + 1)) { Alg->MakeKOptMove(k + m + 1); goto End_PatchCyclesRec; } memcpy(p.get() + 1, pSaved, 2 * k * sizeof(int)); for (i = 1; i <= 2 * k; i++) (*q.get())[(*p.get())[i]] = i; } } } } } } Gain = 0; if (S4) { int OldCycle = *CurrentCycle; if (!pSaved) { assert(pSaved = (int *) malloc(2 * k * sizeof(int))); memcpy(pSaved, p.get() + 1, 2 * k * sizeof(int)); } (*t.get())[2 * (k + m) - 1] = S3; (*t.get())[2 * (k + m)] = S4; (*incl.get())[(*incl.get())[2 * k + 1] = 2 * (k + m)] = 2 * k + 1; /* Find a new alternating cycle */ Alg->PatchingA--; (*RecLevel)++; MarkAdded(s2, S3); MarkDeleted(S3, S4); MarkAdded(S4, s1); Gain = Alg->PatchCycles(k + m, BestCloseUpGain); UnmarkAdded(s2, S3); UnmarkDeleted(S3, S4); UnmarkAdded(S4, s1); (*RecLevel)--; Alg->PatchingA++; if (Gain <= 0) { memcpy(cycle.get() + 1, cycleSaved, 2 * k * sizeof(int)); memcpy(p.get() + 1, pSaved, 2 * k * sizeof(int)); for (i = 1; i <= 2 * k; i++) (*q.get())[(*p.get())[i]] = i; *CurrentCycle = OldCycle; } } End_PatchCyclesRec: free(cycleSaved); free(pSaved); return Gain; }