Example #1
0
void SrvrMergeOverlappingWalls( uint32_t client_id, INDEX iWorld, PORTHOAREA rect )
{
	// for all walls - find a wall without a mate in the rect area...
	// then for all remaining walls - find another wall that is the 
	// same line as this one....
	GETWORLD(iWorld);

	int nwalls, n;
	PWALL *wallarray;
	wallarray = GetLinearWallArray( world->walls, &nwalls );
	for( n = 0; n < nwalls; n++ )
	{
		_POINT start, end;
		PWALL wall = wallarray[n];
		if( wall->iWallInto == INVALID_INDEX )
		{
			PFLATLAND_MYLINESEG line = GetLine( wall->iLine );
			addscaled( start, line->r.o, line->r.n, line->dFrom );
			addscaled( end, line->r.o, line->r.n, line->dTo );
			if( PointInRect( start, rect ) &&
			    PointInRect( end, rect ) )
			{
				int m;
				for( m = n+1; m < nwalls; m++ )
				{
					PWALL wall2 = wallarray[m];
					if( wall2->iWallInto == INVALID_INDEX )
					{
						_POINT start2, end2;
						PFLATLAND_MYLINESEG line = GetLine( wall2->iLine );
						addscaled( start2, line->r.o, line->r.n, line->dFrom );
						addscaled( end2, line->r.o, line->r.n, line->dTo );
						/*
						if( PointInRect( start2, rect ) && 
							 PointInRect( end2, rect ) )
						{
							Log4( "starts: (%12.12g,%12.12g) vs (%12.12g,%12.12g)" 
										,start[0], start[1]
										,start2[0], start2[1] );
							Log4( "ends  : (%12.12g,%12.12g) vs (%12.12g,%12.12g)" 
										,end[0], end[1]
										,end2[0], end2[1] );
						}
						*/
						if( ( Near( start2, start ) &&
						      Near( end2, end ) ) 
						  ||( Near( start2, end ) &&
						      Near( end2, start ) ) )
						{
							SrvrMergeWalls( client_id, iWorld, GetWallIndex( wall ), GetWallIndex( wall2 ) );
							break;
						}

					}
				}
			}
		}	
	}
	Release( wallarray );
}
Example #2
0
bool Connect4GameState::CheckWinDirections(int player, int x, int y)
{
    for (int i = 0; i < 4; ++i)
    {
        if (Near(player, x, y, directions[i][0], directions[i][1])
                + Near(player, x, y, -directions[i][0], -directions[i][1]) >= 3)
        {
            return true;
        }
    }

    return false;
}
Example #3
0
File: bdd.hpp Project: sos22/SLI
		template <typename t> static rank_hint Near(t *what) {
			if (what->isLeaf()) {
				return Start();
			} else {
				return Near(what->internal().rank);
			}
		}
Example #4
0
	void Attack()
	{
		if(Near(Pos, player->Pos))
		{
			player->Score(-1);
			Erase = true;
		}
	}
Example #5
0
    void performTest(int channelsIn, int channelsOut, int code, double threshold = 1e-3)
    {
        for (int j = 0; j < test_loop_times; j++)
        {
            generateTestData(channelsIn, channelsOut);

            OCL_OFF(cv::cvtColor(src_roi, dst_roi, code, channelsOut));
            OCL_ON(cv::cvtColor(usrc_roi, udst_roi, code, channelsOut));

            Near(threshold);
        }
    }
Example #6
0
OCL_TEST_P(CalcBackProject, Mat)
{
    for (int j = 0; j < test_loop_times; j++)
    {
        random_roi();

        OCL_OFF(cv::calcBackProject(images_roi, channels, hist_roi, dst_roi, ranges, scale));
        OCL_ON(cv::calcBackProject(uimages_roi, channels, uhist_roi, udst_roi, ranges, scale));

        Near();
    }
}
Example #7
0
void UnitTest()
{
    assert(Sign(+10) == +1);
    assert(Sign(-10) == -1);
    assert(Sign(0) == 0);

    int n[6] = { 0 };
    for (int i = 0; i < 10000; i++)
        for (int j = 1; j < 6; j++)
            n[j] += (SimpleRNG::ins().Random(j) == 0);
    assert(Near(n[1], 10000, 0));
    assert(Near(n[2], 5000, 250));
    assert(Near(n[3], 3333, 250));
    assert(Near(n[4], 2500, 250));
    assert(Near(n[5], 2000, 250));

    int c = 0;
    for (int i = 0; i < 10000; i++)
        c += SimpleRNG::ins().Bernoulli(0.5);
    assert(Near(c, 5000, 250));
    assert(CheckFlag(5, 0));
    assert(!CheckFlag(5, 1));
    assert(CheckFlag(5, 2));
    assert(!CheckFlag(5, 3));
    int flag = 1;
    SetFlag(flag, 2);
    SetFlag(flag, 4);
    assert(flag == 21);
}
Example #8
0
	void Update()
	{
		if(Near(Pos, player->Pos))
		{
			Visual = ' ';
			Collision = false;
		}
		else
		{
			Visual = '=';
			Collision = true;
		}
	}
Example #9
0
bool PathFind::Search(const Point& first,const Point& second)
{ 
	if(A[first.X][first.Y]!=A[second.X][second.Y])
	{
		return false;
	}
	bool isOK=Near(first,second);
	if(!isOK)
	{
		isOK=OneLine(first,second);
	}
	if(!isOK)
	{
		isOK=MoreLine(first,second);
	}
	return isOK;
}
Example #10
0
	void Update()
	{
		Attack();
		if(Near(Pos, player->Pos, 8))
		{
			if(dir)
			{
				if(Pos.x < player->Pos.x) Pos.x++;
				else if(Pos.x > player->Pos.x) Pos.x--;
			}
			else
			{
				if(Pos.y < player->Pos.y) Pos.y++;
				else if(Pos.y > player->Pos.y) Pos.y--;
			}
		}
		dir = !dir;
	}
Example #11
0
OCL_TEST_F(SphericalWarperTest, Mat)
{
    for (int j = 0; j < test_loop_times; j++)
    {
        generateTestData();

        Ptr<WarperCreator> creator = makePtr<SphericalWarper>();
        Ptr<detail::RotationWarper> warper = creator->create(2.0);

        OCL_OFF(warper->buildMaps(src.size(), K, R, xmap, ymap));
        OCL_ON(warper->buildMaps(usrc.size(), K, R, uxmap, uymap));

        OCL_OFF(warper->warp(src, K, R, INTER_LINEAR, BORDER_REPLICATE, dst));
        OCL_ON(warper->warp(usrc, K, R, INTER_LINEAR, BORDER_REPLICATE, udst));

        Near(1e-4);
    }
}
Example #12
0
unsigned int
KeyFrameSequenceLength( KeyLink * p, double transTolerance, double rotTolerance )
{
  CalVector translation = p->keyframe_->getTranslation();
  CalQuaternion rotation = p->keyframe_->getRotation();
  p = p->next_;
  unsigned int len = 1;
  while( p ) {
    CalVector const ppos = p->keyframe_->getTranslation();
    CalQuaternion const pori = p->keyframe_->getRotation();
    if( Near( translation, rotation, ppos, pori, transTolerance, rotTolerance ) ) {
      len++;
      p = p->next_;
    } else {
      break;
    }
  }
  return len;
}
Example #13
0
bool
CalCoreTrack::keyframeEliminatable( CalCoreKeyframe * prev, 
                                   CalCoreKeyframe * p, 
                                   CalCoreKeyframe * next,
                                   double transTolerance,
                                   double rotTolerance )
{
  CalVector translation;
  CalQuaternion rotation;
  assert( prev && p && next );
  float time = p->getTime();
  float blendFactor;
  blendFactor = ( time - prev->getTime() ) / ( next->getTime() - prev->getTime() );

  // blend between the two keyframes
  translation = prev->getTranslation();
  translation.blend( blendFactor, next->getTranslation() );
  rotation = prev->getRotation();
  rotation.blend( blendFactor, next->getRotation() );
  CalVector const ppos = p->getTranslation();
  CalQuaternion const pori = p->getRotation();
  return Near( translation, rotation, ppos, pori, transTolerance, rotTolerance );
}
Example #14
0
	double Dist(const Line& l, const Point3d& p, Point3d& pnear, double& t){
		// returns the distance of a point from a line and the near point on the extended line and the parameter of the near point (0-length) in range
		pnear = Near(l, p, t );
		return p.Dist(pnear);
	}
Example #15
0
LKH::LKHAlg::Node * LKH::LKHAlg::Best5OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6 = 0, *t7, *t8 = 0, *t9, *t10 = 0;
    Node *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0, *T7 = 0, *T8 = 0, *T9 =
        0, *T10 = 0;
    Candidate *Nt2, *Nt4, *Nt6, *Nt8;
    GainType G1, G2, G3, G4, G5, G6, G7, G8, BestG8 = MINUS_INFINITY;
    int Case6 = 0, Case8 = 0, Case10 = 0, BestCase10 = 0, X4, X6, X8, X10,
        BTW275 = 0, BTW674 = 0,
        BTW571 = 0, BTW376 = 0, BTW574 = 0, BTW671 = 0,
        BTW471 = 0, BTW673 = 0, BTW573 = 0, BTW273 = 0;
    int Breadth2 = 0, Breadth4, Breadth6, Breadth8;

    if (t2 != SUC(t1))
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6,T7,T8,T9,T10) = (t3,t4,t5,t6,t7,t8,t9,t10)
     * such that
     *
     *     G8 = *G0 - C(t2,T3) + C(T3,T4)
     *              - C(T4,T5) + C(T5,T6)
     *              - C(T6,T7) + C(T7,T8)
     *              - C(T8,T9) + C(T9,T10)
     *
     * is maximum (= BestG8), and (T9,T10) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best5OptMove immediately. 
     */

    /* 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 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + (this->*C)(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - (this->*c)(t4, t1) > 0) && (*Gain = G2 - (this->*C)(t4, t1)) > 0)
            {
                Make2OptMove(t1, t2, t3, t4);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed &&
                     ProblemType != HCP && ProblemType != HPP))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= 2; X6++) {
                    if (X4 == 1) {
                        if (X6 == 1) {
                            Case6 = 1 + !BETWEEN(t2, t5, t4);
                            t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                        } else {
                            t6 = t6 == t5->Pred ? t5->Suc : t5->Pred;
                            if ((t5 == t1 && t6 == t2) ||
                                (t5 == t2 && t6 == t1))
                                continue;
                            Case6 += 2;
                        }
                    } else if (BETWEEN(t2, t5, t3)) {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    } else {
                        Case6 = 6 + X6;
                        t6 = X6 == 1 ? PRED(t5) : SUC(t5);
                        if (t6 == t2)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + (this->*C)(t5, t6);
                    if ((Case6 <= 2 || Case6 == 5 || Case6 == 6) &&
                        !Forbidden(t6, t1) &&
                        (!c || G4 - (this->*c)(t6, t1) > 0) &&
                        (*Gain = G4 - (this->*C)(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (Backtracking && !Excludable(t5, t6))
                        continue;
                    Breadth6 = 0;
                    /* Choose (t6,t7) as a candidate edge emanating from t6 */
                    for (Nt6 = t6->CandidateSet; (t7 = Nt6->To); Nt6++) {
                        if (t7 == t6->Pred || t7 == t6->Suc ||
                            (t6 == t2 && t7 == t3) ||
                            (t6 == t3 && t7 == t2) ||
                            ((G5 = G4 - Nt6->Cost) <= 0 &&
                             GainCriterionUsed &&
                             ProblemType != HCP && ProblemType != HPP))
                            continue;
                        if (++Breadth6 > MaxBreadth)
                            break;
                        /* Choose t8 as one of t7's two neighbors on the tour */
                        for (X8 = 1; X8 <= 2; X8++) {
                            if (X8 == 1) {
                                Case8 = Case6;
                                switch (Case6) {
                                case 1:
                                    if ((BTW275 = BETWEEN(t2, t7, t5)))
                                        t8 = SUC(t7);
                                    else {
                                        t8 = PRED(t7);
                                        BTW674 = BETWEEN(t6, t7, t4);
                                    }
                                    break;
                                case 2:
                                    if ((BTW376 = BETWEEN(t3, t7, t6)))
                                        t8 = SUC(t7);
                                    else {
                                        t8 = PRED(t7);
                                        BTW571 = BETWEEN(t5, t7, t1);
                                    }
                                    break;
                                case 3:
                                    t8 = SUC(t7);
                                    BTW574 = BETWEEN(t5, t7, t4);
                                    break;
                                case 4:
                                    if ((BTW671 = BETWEEN(t6, t7, t1)))
                                        t8 = PRED(t7);
                                    else
                                        t8 = BETWEEN(t2, t7,
                                                     t4) ? SUC(t7) :
                                            PRED(t7);
                                    break;
                                case 5:
                                    t8 = PRED(t7);
                                    BTW471 = BETWEEN(t4, t7, t1);
                                    if (!BTW471)
                                        BTW673 = BETWEEN(t6, t7, t3);
                                    break;
                                case 6:
                                    if ((BTW471 = BETWEEN(t4, t7, t1)))
                                        t8 = PRED(t7);
                                    else {
                                        t8 = SUC(t7);
                                        BTW573 = BETWEEN(t5, t7, t3);
                                    }
                                    break;
                                case 7:
                                case 8:
                                    t8 = SUC(t7);
                                    BTW273 = BETWEEN(t2, t7, t3);
                                    break;
                                }
                            } else {
                                t8 = t8 == t7->Pred ? t7->Suc : t7->Pred;
                                Case8 += 8;
                            }
                            if ((t7 == t1 && t8 == t2) ||
                                (t7 == t2 && t8 == t1) ||
                                (t7 == t3 && t8 == t4) ||
                                (t7 == t4 && t8 == t3))
                                continue;
                            if (FixedOrCommon(t7, t8))
                                continue;
                            if (Case6 == 3 && !BTW574 &&
                                (X8 == 1) == BETWEEN(t3, t7, t1))
                                continue;
                            if (Case6 == 4 && BTW671 && X8 == 2)
                                break;
                            if (Case6 == 7 && !BTW273 &&
                                (X8 == 1) == BETWEEN(t5, t7, t1))
                                continue;
                            if (Case6 == 8 && !BTW273
                                && !BETWEEN(t4, t7, t5))
                                break;
                            G6 = G5 + (this->*C)(t7, t8);
                            if (t8 != t1 &&
                                (Case6 == 3 ? BTW574 :
                                 Case6 == 4 ? !BTW671 :
                                 Case6 == 7 ? BTW273 :
                                 Case6 != 8 && X8 == 1) &&
                                !Forbidden(t8, t1) &&
                                (!c || G6 - (this->*c)(t8, t1) > 0) &&
                                (*Gain = G6 - (this->*C)(t8, t1)) > 0) {
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                return 0;
                            }
                            if (Backtracking && !Excludable(t7, t8))
                                continue;
                            Breadth8 = 0;
                            /* Choose (t8,t9) as a candidate edge emanating 
                               from t8 */
                            for (Nt8 = t8->CandidateSet; (t9 = Nt8->To);
                                 Nt8++) {
                                if (t9 == t8->Pred || t9 == t8->Suc
                                    || t9 == t1 || (t8 == t2 && t9 == t3)
                                    || (t8 == t3 && t9 == t2) || (t8 == t4
                                                                  && t9 ==
                                                                  t5)
                                    || (t8 == t5 && t9 == t4)
                                    || ((G7 = G6 - Nt8->Cost) <= 0
                                        && GainCriterionUsed
                                        && ProblemType != HCP
                                        && ProblemType != HPP))
                                    continue;
                                if (++Breadth8 > MaxBreadth)
                                    break;
                                /* Choose t10 as one of t9's two neighbors 
                                   on the tour */
                                for (X10 = 1; X10 <= 2; X10++) {
                                    if (X10 == 1) {
                                        t10 = 0;
                                        switch (Case8) {
                                        case 1:
                                            t10 = (BTW275 ?
                                                   BETWEEN(t8, t9, t5)
                                                   || BETWEEN(t3, t9,
                                                              t1) : BTW674
                                                   ? BETWEEN(t7, t9,
                                                             t1) :
                                                   BETWEEN(t7, t9,
                                                           t5)) ? PRED(t9)
                                                : SUC(t9);
                                            Case10 = 22;
                                            break;
                                        case 2:
                                            t10 = (BTW376 ?
                                                   BETWEEN(t8, t9, t4) :
                                                   BTW571 ?
                                                   BETWEEN(t7, t9, t1)
                                                   || BETWEEN(t3, t9,
                                                              t6) :
                                                   BETWEEN(t7, t9,
                                                           t1)) ? PRED(t9)
                                                : SUC(t9);
                                            Case10 = 23;
                                            break;
                                        case 3:
                                            if (BTW574) {
                                                t10 = BETWEEN(t5, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 24;
                                                break;
                                            }
                                            if (!BETWEEN(t5, t9, t4))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 1;
                                            break;
                                        case 4:
                                            if (BTW671) {
                                                if (!BETWEEN(t2, t9, t5))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 2;
                                                break;
                                            }
                                            t10 = BETWEEN(t6, t9, t4) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 25;
                                            break;
                                        case 5:
                                            t10 = (BTW471 ?
                                                   BETWEEN(t7, t9, t1) :
                                                   BTW673 ?
                                                   BETWEEN(t7, t9, t5) :
                                                   BETWEEN(t4, t9, t1)
                                                   || BETWEEN(t7, t9,
                                                              t5)) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 26;
                                            break;
                                        case 6:
                                            t10 = (BTW471 ?
                                                   BETWEEN(t7, t9, t3) :
                                                   BTW573 ?
                                                   BETWEEN(t8, t9, t6) :
                                                   BETWEEN(t4, t9, t1)
                                                   || BETWEEN(t8, t9,
                                                              t6)) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 27;
                                            break;
                                        case 7:
                                            if (BTW273) {
                                                t10 = BETWEEN(t5, t9, t3) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 28;
                                                break;
                                            }
                                            if (!BETWEEN(t2, t9, t3))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 3;
                                            break;
                                        case 8:
                                            if (BTW273) {
                                                if (!BETWEEN(t4, t9, t5))
                                                    break;
                                                Case10 = 4;
                                            } else {
                                                if (!BETWEEN(t2, t9, t3))
                                                    break;
                                                Case10 = 5;
                                            }
                                            t10 = SUC(t9);
                                            break;
                                        case 9:
                                            if (BTW275) {
                                                if (!BETWEEN(t7, t9, t4))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 6;
                                                break;
                                            }
                                            if (!BTW674) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 7;
                                                break;
                                            }
                                            if (!BETWEEN(t6, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 8;
                                            break;
                                        case 10:
                                            if (BTW376) {
                                                if (!BETWEEN(t7, t9, t6))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 9;
                                                break;
                                            }
                                            if (BTW571) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 10;
                                                break;
                                            }
                                            if (!BETWEEN(t3, t9, t6) &&
                                                !BETWEEN(t2, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 11;
                                            break;
                                        case 11:
                                            if (BTW574) {
                                                t10 = BETWEEN(t3, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 29;
                                                break;
                                            }
                                            if (!BETWEEN(t5, t9, t4))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 12;
                                            break;
                                        case 12:
                                            t10 = BETWEEN(t3, t9, t1) ?
                                                PRED(t9) : SUC(t9);
                                            Case10 = 30;
                                            break;
                                        case 13:
                                            if (BTW471) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 13;
                                                break;
                                            }
                                            if (BTW673) {
                                                if (!BETWEEN(t6, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 14;
                                                break;
                                            }
                                            if (!BETWEEN(t6, t9, t3) &&
                                                !BETWEEN(t2, t9, t7))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 15;
                                            break;
                                        case 14:
                                            if (BTW471) {
                                                if (!BETWEEN(t2, t9, t7))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 16;
                                                break;
                                            }
                                            if (BTW573) {
                                                if (!BETWEEN(t7, t9, t3) &&
                                                    !BETWEEN(t2, t9, t6))
                                                    break;
                                                t10 = SUC(t9);
                                                Case10 = 17;
                                                break;
                                            }
                                            if (!BETWEEN(t7, t9, t6))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 18;
                                            break;
                                        case 15:
                                            if (BTW273) {
                                                t10 = BETWEEN(t5, t9, t1) ?
                                                    PRED(t9) : SUC(t9);
                                                Case10 = 31;
                                                break;
                                            }
                                            if (!BETWEEN(t2, t9, t3))
                                                break;
                                            t10 = SUC(t9);
                                            Case10 = 19;
                                            break;
                                        case 16:
                                            if (BTW273) {
                                                if (!BETWEEN(t4, t9, t5))
                                                    break;
                                                Case10 = 20;
                                            } else {
                                                if (!BETWEEN(t2, t9, t3))
                                                    break;
                                                Case10 = 21;
                                            }
                                            t10 = SUC(t9);
                                            break;
                                        }
                                        if (!t10)
                                            break;
                                    } else {
                                        if (Case10 >= 22)
                                            continue;
                                        Case10 += 31;
                                        t10 =
                                            t10 ==
                                            t9->Pred ? t9->Suc : t9->Pred;
                                    }
                                    if (t10 == t1 ||
                                        (t9 == t3 && t10 == t4) ||
                                        (t9 == t4 && t10 == t3) ||
                                        (t9 == t5 && t10 == t6) ||
                                        (t9 == t6 && t10 == t5))
                                        continue;
                                    if (FixedOrCommon(t9, t10))
                                        continue;
                                    G8 = G7 + (this->*C)(t9, t10);
                                    if (!Forbidden(t10, t1) &&
                                        (!c || G8 - (this->*c)(t10, t1) > 0) &&
                                        (*Gain = G8 - (this->*C)(t10, t1)) > 0) {
                                        Make5OptMove(t1, t2, t3, t4, t5,
                                                     t6, t7, t8, t9, t10,
                                                     Case10);
                                        return 0;
                                    }
                                    if (GainCriterionUsed &&
                                        G8 - Precision < t10->Cost)
                                        continue;
                                    if (!Backtracking || Swaps > 0) {
                                        if ((G8 > BestG8 ||
                                             (G8 == BestG8 && !Near(t9, t10)
                                              && Near(T9, T10)))
                                            && Swaps < MaxSwaps
                                            && Excludable(t9, t10)
                                            && !InInputTour(t9, t10)) {
                                            /* Ignore the move if the gain does
                                               not vary */
                                            if (RestrictedSearch &&
                                                ProblemType != HCP &&
                                                ProblemType != HPP &&
                                                G2 - t4->Pi == G4 - t6->Pi && 
                                                G4 - t6->Pi == G6 - t8->Pi &&
                                                G6 - t8->Pi == G8 - t10->Pi &&
                                                G3 + t5->Pi == G1 + t3->Pi &&
                                                G5 + t7->Pi == G3 + t5->Pi &&
                                                G7 + t9->Pi == G5 + t7->Pi)
                                                continue;
                                            T3 = t3;
                                            T4 = t4;
                                            T5 = t5;
                                            T6 = t6;
                                            T7 = t7;
                                            T8 = t8;
                                            T9 = t9;
                                            T10 = t10;
                                            BestCase10 = Case10;
                                            BestG8 = G8;
                                        }
                                    } else if (MaxSwaps > 0) {
                                        GainType G = G8;
                                        Node *t = t10;
                                        Make5OptMove(t1, t2, t3, t4, t5,
                                                     t6, t7, t8, t9, t10,
                                                     Case10);
                                        Exclude(t1, t2);
                                        Exclude(t3, t4);
                                        Exclude(t5, t6);
                                        Exclude(t7, t8);
                                        Exclude(t9, t10);
                                        while ((t =
                                                (this->*BestSubsequentMove)(t1, t,
                                                                   &G,
                                                                   Gain)));
                                        if (*Gain > 0)
                                            return 0;
                                        RestoreTour();
                                        if (t2 != SUC(t1))
                                            Reversed ^= 1;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T10) {
        /* Make the best 5-opt move */
        Make5OptMove(t1, t2, T3, T4, T5, T6, T7, T8, T9, T10, BestCase10);
        Exclude(t1, t2);
        Exclude(T3, T4);
        Exclude(T5, T6);
        Exclude(T7, T8);
        Exclude(T9, T10);
        *G0 = BestG8;
    }
    return T10;
}
Example #16
0
void MergePatternsAntiPar(STRIDE_PATTERN **Pat, int NPat)
{
  register int i, j;
  int DB, DW, MinDB1, MinDB2, MinDW1, MinDW2, Min, Lnk1A, Lnk1D;
  int I1A, I1D, I2A, I2D, J1A, J1D, J2A, J2D;
  char I1ACn, I1DCn, I2ACn, I2DCn, J1ACn, J1DCn, J2ACn, J2DCn;

  for( i=0; i<NPat; i++ ) {

    if( !Pat[i]->ExistPattern ) continue;

    MinDB1 = MinDB2 = MinDW1 = MinDW2 = 1000;
    Min = ERR;
    Lnk1D = Lnk1A = ERR;

    Alias(&I1D,&I1A,&I2D,&I2A,&I1DCn,&I1ACn,&I2DCn,&I2ACn,Pat[i]);

    for( j=0; j<NPat; j++ ) {

      if( i == j || !Pat[j]->ExistPattern ) continue;

      Alias(&J1D,&J1A,&J2D,&J2A,&J1DCn,&J1ACn,&J2DCn,&J2ACn,Pat[j]);
      
      if( Near(I1D,J1D,J1A,I1A,J2A,J2D,I2A,I2D,I1DCn,J1DCn,J1ACn,I1ACn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J1A,J1D,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J2D,&Lnk1D,J2A,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1D,J1A,J1D,I1A,J2D,J2A,I2A,I2D,I1DCn,J1ACn,J1DCn,I1ACn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J1D,J1A,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J2A,&Lnk1D,J2D,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1D,J2D,J2A,I1A,J1A,J1D,I2A,I2D,I1DCn,J2DCn,J2ACn,I1ACn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J2A,J2D,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J1D,&Lnk1D,J1A,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1D,J2A,J2D,I1A,J1D,J1A,I2A,I2D,I1DCn,J2ACn,J2DCn,I1ACn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J2D,J2A,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J1A,&Lnk1D,J1D,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1A,J1D,J1A,I1D,J2A,J2D,I2D,I2A,I1ACn,J1DCn,J1ACn,I1DCn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J1A,J1D,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J2A,&Lnk1D,J2D,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1A,J1A,J1D,I1D,J2D,J2A,I2D,I2A,I1ACn,J1ACn,J1DCn,I1DCn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J1A,J1D,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J2D,&Lnk1D,J2A,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1A,J2D,J2A,I1D,J1A,J1D,I2D,I2A,I1ACn,J2DCn,J2ACn,I1DCn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J2D,J2A,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J1A,&Lnk1D,J1D,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

      if( Near(I1A,J2A,J2D,I1D,J1D,J1A,I2D,I2A,I1ACn,J2ACn,J2DCn,I1DCn,&DB,&DW) && 
	  ((DB < MinDB1 && DW <= MinDW1) || (DB <= MinDB1 && DW < MinDW1) ) && 
	 RightSide(J2A,J2D,I1A,I1D,I2A,I2D) )
	JoinNeighbours(&Lnk1A,J1D,&Lnk1D,J2D,&Pat[i]->Nei1,Pat[j],&MinDB1,DB,&MinDW1,DW,&Min,j);

    }

    for( j=0; j<NPat; j++ ) {

      if( j == Min || j == i || !Pat[j]->ExistPattern ) continue;

      Alias(&J1D,&J1A,&J2D,&J2A,&J1DCn,&J1ACn,&J2DCn,&J2ACn,Pat[j]);

      if( Near(I2D,J1D,J1A,I2A,J2A,J2D,I1A,I1D,I2DCn,J1DCn,J1ACn,I2ACn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J2A,J2D,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2D,J1A,J1D,I2A,J2D,J2A,I1A,I1D,I2DCn,J1ACn,J1DCn,I2ACn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J2D,J2A,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2D,J2D,J2A,I2A,J1A,J1D,I1A,I1D,I2DCn,J2DCn,J2ACn,I2ACn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J1A,J1D,I1A,I1D,I2A,I2D) ) 
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2D,J2A,J2D,I2A,J1D,J1A,I1A,I1D,I2DCn,J2ACn,J2DCn,I2ACn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J1D,J1A,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2A,J1D,J1A,I2D,J2A,J2D,I1D,I1A,I2ACn,J1DCn,J1ACn,I2DCn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J2D,J2A,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2A,J1A,J1D,I2D,J2D,J2A,I1D,I1A,I2ACn,J1ACn,J1DCn,I2DCn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J2A,J2D,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2A,J2D,J2A,I2D,J1A,J1D,I1D,I1A,I2ACn,J2DCn,J2ACn,I2DCn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J1D,J1A,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      
      if( Near(I2A,J2A,J2D,I2D,J1D,J1A,I1D,I1A,I2ACn,J2ACn,J2DCn,I2DCn,&DB,&DW) && 
	  (( DB < MinDB2 && DW <= MinDW2) || (DB <= MinDB2 && DW < MinDW2) ) &&
	 RightSide2(Lnk1A,Lnk1D,J1A,J1D,I1A,I1D,I2A,I2D) )
	JoinNeighb(&Pat[i]->Nei2,Pat[j],&MinDB2,DB,&MinDW2,DW);
      }
  }
}
Example #17
0
bool PathFind::Near(TwoPoint& endPoint)
{  
	Point& first=endPoint.First();
	Point& second=endPoint.Second();
	return  Near(first,second);
}
Example #18
0
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;
}
Example #19
0
Node *Best2OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *T3 = 0, *T4 = 0;
    Candidate *Nt2;
    GainType G1, G2, BestG2 = MINUS_INFINITY;
    int Breadth2 = 0;

    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4) = (t3,t4)
     * such that 
     *
     *     G4 = *G0 - C(t2,T3) + C(T3,T4)
     *
     * is maximum (= BestG2), and (T3,T4) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best2OptMove immediately 
     */

    /* 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 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        /* Choose t4 (only one choice gives a closed tour) */
        t4 = PRED(t3);
        if (FixedOrCommon(t3, t4))
            continue;
        G2 = G1 + C(t3, t4);
        if (!Forbidden(t4, t1) &&
            (!c || G2 - c(t4, t1) > 0) && (*Gain = G2 - C(t4, t1)) > 0) {
            Swap1(t1, t2, t3);
            *G0 = G2;
            return 0;
        }
        if (++Breadth2 > MaxBreadth)
            break;
        if (GainCriterionUsed && G2 - Precision < t4->Cost)
            continue;
        if (!Backtracking || Swaps > 0) {
            if (G2 > BestG2 &&
                Swaps < MaxSwaps &&
                Excludable(t3, t4) && (!InInputTour(t3, t4)
                                       || !Near(t3, t4))) {
                T3 = t3;
                T4 = t4;
                BestG2 = G2;
            }
        } else if (MaxSwaps > 0) {
            GainType G = G2;
            Node *t = t4;
            Make2OptMove(t1, t2, t3, t4);
            Exclude(t1, t2);
            Exclude(t3, t4);
            while ((t = BestSubsequentMove(t1, t, &G, Gain)));
            if (*Gain > 0)
                return 0;
            RestoreTour();
            if (t2 != SUC(t1))
                Reversed ^= 1;
        }
    }
    *Gain = 0;
    if (T4) {
        /* Make the best 2-opt move */
        Swap1(t1, t2, T3);
        Exclude(t1, t2);
        Exclude(T3, T4);
        *G0 = BestG2;
    }
    return T4;
}
Example #20
0
GainType LinKernighan()
{
    Node *t1, *t2, *SUCt1;
    GainType Gain, G0, Cost;
    int X2, i, it = 0;
    Candidate *Nt1;
    Segment *S;
    SSegment *SS;
    double EntryTime = GetTime();

    Reversed = 0;
    S = FirstSegment;
    i = 0;
    do {
        S->Size = 0;
        S->Rank = ++i;
        S->Reversed = 0;
        S->First = S->Last = 0;
    }
    while ((S = S->Suc) != FirstSegment);
    SS = FirstSSegment;
    i = 0;
    do {
        SS->Size = 0;
        SS->Rank = ++i;
        SS->Reversed = 0;
        SS->First = SS->Last = 0;
    }
    while ((SS = SS->Suc) != FirstSSegment);

    FirstActive = LastActive = 0;
    Swaps = 0;

    /* Compute the cost of the initial tour, Cost.
       Compute the corresponding hash value, Hash.
       Initialize the segment list.
       Make all nodes "active" (so that they can be used as t1). */
    Cost = 0;
    Hash = 0;
    i = 0;
    t1 = FirstNode;
    do {
        t2 = t1->OldSuc = t1->Suc;
        t1->OldPred = t1->Pred;
        t1->Rank = ++i;
        Cost += (t1->SucCost = t2->PredCost = C(t1, t2)) - t1->Pi - t2->Pi;
        Hash ^= Rand[t1->Id] * Rand[t2->Id];
        t1->Cost = INT_MAX;
        for (Nt1 = t1->CandidateSet; (t2 = Nt1->To); Nt1++)
            if (t2 != t1->Pred && t2 != t1->Suc && Nt1->Cost < t1->Cost)
                t1->Cost = Nt1->Cost;
        t1->Parent = S;
        S->Size++;
        if (S->Size == 1)
            S->First = t1;
        S->Last = t1;
        if (SS->Size == 0)
            SS->First = S;
        S->Parent = SS;
        SS->Last = S;
        if (S->Size == GroupSize) {
            S = S->Suc;
            SS->Size++;
            if (SS->Size == SGroupSize)
                SS = SS->Suc;
        }
        t1->OldPredExcluded = t1->OldSucExcluded = 0;
        t1->Next = 0;
        if (KickType == 0 || Kicks == 0 ||
            !InBestTour(t1, t1->Pred) || !InBestTour(t1, t1->Suc))
            Activate(t1);
    }
    while ((t1 = t1->Suc) != FirstNode);
    if (S->Size < GroupSize)
        SS->Size++;
    Cost /= Precision;
    if (TraceLevel >= 3 || (TraceLevel == 2 && Cost < BetterCost)) {
        printff("Cost = " GainFormat, Cost);
        if (Optimum != MINUS_INFINITY && Optimum != 0)
            printff(", Gap = %0.4f%%", 100.0 * (Cost - Optimum) / Optimum);
        printff(", Time = %0.1f sec. %s\n", fabs(GetTime() - EntryTime),
                Cost < Optimum ? "<" : Cost == Optimum ? "=" : "");
    }
    PredSucCostAvailable = 1;

    /* Loop as long as improvements are found */
    do {
        /* Choose t1 as the first "active" node */
        while ((t1 = RemoveFirstActive())) {
            /* t1 is now "passive" */
            SUCt1 = SUC(t1);
            if ((TraceLevel >= 3 || (TraceLevel == 2 && Trial == 1)) &&
                ++it % (Dimension >= 100000 ? 10000 :
                        Dimension >= 10000 ? 1000 : 100) == 0)
                printff("#%d: Time = %0.1f sec.\n",
                        it, fabs(GetTime() - EntryTime));
            /* Choose t2 as one of t1's two neighbors on the tour */
            for (X2 = 1; X2 <= 2; X2++) {
                t2 = X2 == 1 ? PRED(t1) : SUCt1;
                if (FixedOrCommon(t1, t2) ||
                    (RestrictedSearch && Near(t1, t2) &&
                     (Trial == 1 ||
                      (Trial > BackboneTrials &&
                       (KickType == 0 || Kicks == 0)))))
                    continue;
                G0 = C(t1, t2);
                /* Try to find a tour-improving chain of moves */
                do
                    t2 = Swaps == 0 ? BestMove(t1, t2, &G0, &Gain) :
                        BestSubsequentMove(t1, t2, &G0, &Gain);
                while (t2);
                if (Gain > 0) {
                    /* An improvement has been found */
                    assert(Gain % Precision == 0);
                    Cost -= Gain / Precision;
                    if (TraceLevel >= 3 ||
                        (TraceLevel == 2 && Cost < BetterCost)) {
                        printff("Cost = " GainFormat, Cost);
                        if (Optimum != MINUS_INFINITY && Optimum != 0)
                            printff(", Gap = %0.4f%%",
                                    100.0 * (Cost - Optimum) / Optimum);
                        printff(", Time = %0.1f sec. %s\n",
                                fabs(GetTime() - EntryTime),
                                Cost < Optimum ? "<" : Cost ==
                                Optimum ? "=" : "");
                    }
                    StoreTour();
                    if (HashSearch(HTable, Hash, Cost))
                        goto End_LinKernighan;
                    /* Make t1 "active" again */
                    Activate(t1);
                    break;
                }
                RestoreTour();
            }
        }
        if (HashSearch(HTable, Hash, Cost))
            goto End_LinKernighan;
        HashInsert(HTable, Hash, Cost);
        /* Try to find improvements using non-sequential 4/5-opt moves */
        Gain = 0;
        if (Gain23Used && (Gain = Gain23()) > 0) {
            /* An improvement has been found */
            assert(Gain % Precision == 0);
            Cost -= Gain / Precision;
            StoreTour();
            if (TraceLevel >= 3 || (TraceLevel == 2 && Cost < BetterCost)) {
                printff("Cost = " GainFormat, Cost);
                if (Optimum != MINUS_INFINITY && Optimum != 0)
                    printff(", Gap = %0.4f%%",
                            100.0 * (Cost - Optimum) / Optimum);
                printff(", Time = %0.1f sec. + %s\n",
                        fabs(GetTime() - EntryTime),
                        Cost < Optimum ? "<" : Cost == Optimum ? "=" : "");
            }
            if (HashSearch(HTable, Hash, Cost))
                goto End_LinKernighan;
        }
    }
    while (Gain > 0);

  End_LinKernighan:
    PredSucCostAvailable = 0;
    NormalizeNodeList();
    NormalizeSegmentList();
    return Cost;
}
Example #21
0
LKH::LKHAlg::Node * LKH::LKHAlg::Best4OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6 = 0, *t7, *t8 = 0,
        *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0, *T7 = 0, *T8 = 0;
    Candidate *Nt2, *Nt4, *Nt6;
    GainType G1, G2, G3, G4, G5, G6, BestG6 = MINUS_INFINITY;
    int Case6 = 0, Case8 = 0, BestCase8 = 0, X4, X6, X8;
    int Breadth2 = 0, Breadth4, Breadth6;

    *Gain = 0;
    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6,T7,T8) = (t3,t4,t5,t6,t7,t8)
     * such that
     *
     *     G8 = *G0 - C(t2,T3) + C(T3,T4) 
     *              - C(T4,T5) + C(T5,T6)
     *              - C(T6,T7) + C(T7,T8)
     *
     * is maximum (= BestG6), and (T7,T8) has not previously been included.
     * If during this process a legal move with *Gain > 0 is found, then make
     * the move and exit Best4OptMove immediately. 
     */

    /* 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 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + (this->*C)(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - (this->*c)(t4, t1) > 0) && (*Gain = G2 - (this->*C)(t4, t1)) > 0)
            {
                Swap1(t1, t2, t3);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed &&
                     ProblemType != HCP && ProblemType != HPP))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= 2; X6++) {
                    if (X4 == 1) {
                        if (X6 == 1) {
                            Case6 = 1 + !BETWEEN(t2, t5, t4);
                            t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                        } else {
                            t6 = t6 == t5->Pred ? t5->Suc : t5->Pred;
                            if ((t5 == t1 && t6 == t2) ||
                                (t5 == t2 && t6 == t1))
                                continue;
                            Case6 += 2;
                        }
                    } else if (BETWEEN(t2, t5, t3)) {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    } else {
                        if (X6 == 2)
                            break;
                        Case6 = 7;
                        t6 = PRED(t5);
                        if (t6 == t2)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + (this->*C)(t5, t6);
                    if ((Case6 <= 2 || Case6 == 5 || Case6 == 6) &&
                        !Forbidden(t6, t1) &&
                        (!c || G4 - (this->*c)(t6, t1) > 0) &&
                        (*Gain = G4 - (this->*C)(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (Backtracking && !Excludable(t5, t6))
                        continue;
                    Breadth6 = 0;
                    /* Choose (t6,t7) as a candidate edge emanating from t6 */
                    for (Nt6 = t6->CandidateSet; (t7 = Nt6->To); Nt6++) {
                        if (t7 == t6->Pred || t7 == t6->Suc ||
                            (t6 == t2 && t7 == t3) ||
                            (t6 == t3 && t7 == t2) ||
                            ((G5 = G4 - Nt6->Cost) <= 0 &&
                             GainCriterionUsed &&
                             ProblemType != HCP && ProblemType != HPP))
                            continue;
                        if (++Breadth6 > MaxBreadth)
                            break;
                        /* Choose t8 as one of t7's two neighbors on the tour */
                        for (X8 = 1; X8 <= 2; X8++) {
                            if (X8 == 1) {
                                Case8 = Case6;
                                t8 = 0;
                                switch (Case6) {
                                case 1:
                                    t8 = BETWEEN(t2, t7,
                                                 t5) ? SUC(t7) : PRED(t7);
                                    break;
                                case 2:
                                    t8 = BETWEEN(t3, t7,
                                                 t6) ? SUC(t7) : PRED(t7);
                                    break;
                                case 3:
                                    if (BETWEEN(t5, t7, t4))
                                        t8 = SUC(t7);
                                    break;
                                case 4:
                                    if (BETWEEN(t2, t7, t5))
                                        t8 = BETWEEN(t2, t7,
                                                     t4) ? SUC(t7) :
                                            PRED(t7);
                                    break;
                                case 5:
                                    t8 = PRED(t7);
                                    break;
                                case 6:
                                    t8 = BETWEEN(t2, t7,
                                                 t3) ? SUC(t7) : PRED(t7);
                                    break;
                                case 7:
                                    if (BETWEEN(t2, t7, t3))
                                        t8 = SUC(t7);
                                    break;
                                }
                                if (t8 == 0)
                                    break;
                            } else {
                                if (Case6 != 3 && Case6 != 4 && Case6 != 7)
                                    break;
                                t8 = t8 == t7->Pred ? t7->Suc : t7->Pred;
                                Case8 += 8;
                            }
                            if (t8 == t1 ||
                                (t7 == t3 && t8 == t4) ||
                                (t7 == t4 && t8 == t3))
                                continue;
                            if (FixedOrCommon(t7, t8))
                                continue;
                            G6 = G5 + (this->*C)(t7, t8);
                            if (t8 != t1 &&
                                !Forbidden(t8, t1) &&
                                (!c || G6 - (this->*c)(t8, t1) > 0) &&
                                (*Gain = G6 - (this->*C)(t8, t1)) > 0) {
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                return 0;
                            }
                            if (GainCriterionUsed &&
                                G6 - Precision < t8->Cost)
                                continue;
                            if (!Backtracking || Swaps > 0) {
                                if ((G6 > BestG6 ||
                                     (G6 == BestG6 && !Near(t7, t8) &&
                                      Near(T7, T8))) &&
                                    Swaps < MaxSwaps &&
                                    Excludable(t7, t8) &&
                                    !InInputTour(t7, t8)) {
                                    /* Ignore the move if the gain does 
                                       not vary */
                                    if (RestrictedSearch &&
                                        ProblemType != HCP &&
                                        ProblemType != HPP &&
                                        G2 - t4->Pi == G4 - t6->Pi &&
                                        G4 - t6->Pi == G6 - t8->Pi &&
                                        G3 + t5->Pi == G1 + t3->Pi &&
                                        G5 + t7->Pi == G3 + t5->Pi)
                                        continue;
                                    T3 = t3;
                                    T4 = t4;
                                    T5 = t5;
                                    T6 = t6;
                                    T7 = t7;
                                    T8 = t8;
                                    BestCase8 = Case8;
                                    BestG6 = G6;
                                }
                            } else if (MaxSwaps > 0) {
                                GainType G = G6;
                                Node *t = t8;
                                Make4OptMove(t1, t2, t3, t4, t5, t6, t7,
                                             t8, Case8);
                                Exclude(t1, t2);
                                Exclude(t3, t4);
                                Exclude(t5, t6);
                                Exclude(t7, t8);
                                while ((t =
                                        (this->*BestSubsequentMove)(t1, t, &G,
                                                           Gain)));
                                if (*Gain > 0)
                                    return 0;
                                RestoreTour();
                                if (t2 != SUC(t1))
                                    Reversed ^= 1;
                            }
                        }
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T8) {
        /* Make the best 4-opt move */
        Make4OptMove(t1, t2, T3, T4, T5, T6, T7, T8, BestCase8);
        Exclude(t1, t2), Exclude(T3, T4);
        Exclude(T5, T6);
        Exclude(T7, T8);
        *G0 = BestG6;
    }
    return T8;
}
Example #22
0
int main() {
	Average data(0.0);

	assert(data.size() == 1);
	assert(data.max_size() == 6);
	assert(data.getHistoricValue(0) == 0.0);
	assert(data.getAverage() == 0.0);

	data.setValue(1.1);
	assert(data.size() == 2);
	assert(data.getValue() == 1.1);
	assert(data.getHistoricValue(0) == 1.1);
	assert(data.getHistoricValue(1) == 0.0);
	assert(data.getAverage() == Near(1.1/2));

	data.setValue(2.2);
	assert(data.size() == 3);
	assert(data.getValue() == 2.2);
	assert(data.getHistoricValue(0) == 2.2);
	assert(data.getHistoricValue(1) == 1.1);
	assert(data.getHistoricValue(2) == 0.0);
	assert(data.getAverage() == Near(3.3/3));

	data.setValue(3.3);
	assert(data.size() == 4);
	assert(data.getValue() == 3.3);
	assert(data.getHistoricValue(0) == 3.3);
	assert(data.getHistoricValue(1) == 2.2);
	assert(data.getHistoricValue(2) == 1.1);
	assert(data.getHistoricValue(3) == 0.0);
	assert(data.getAverage() == Near(6.6/4));

	data.setValue(4.4);
	assert(data.size() == 5);
	assert(data.getValue() == 4.4);
	assert(data.getHistoricValue(0) == 4.4);
	assert(data.getHistoricValue(1) == 3.3);
	assert(data.getHistoricValue(2) == 2.2);
	assert(data.getHistoricValue(3) == 1.1);
	assert(data.getHistoricValue(4) == 0.0);
	assert(data.getAverage() == Near(11.0/5));

	data.setValue(5.5);
	assert(data.size() == 6);
	assert(data.getValue() == 5.5);
	assert(data.getHistoricValue(0) == 5.5);
	assert(data.getHistoricValue(1) == 4.4);
	assert(data.getHistoricValue(2) == 3.3);
	assert(data.getHistoricValue(3) == 2.2);
	assert(data.getHistoricValue(4) == 1.1);
	assert(data.getHistoricValue(5) == 0.0);
	assert(data.getAverage() == Near(16.5/6));

	data.setValue(6.6);
	assert(data.size() == 6);
	assert(data.getValue() == 6.6);
	assert(data.getHistoricValue(0) == 6.6);
	assert(data.getHistoricValue(1) == 5.5);
	assert(data.getHistoricValue(2) == 4.4);
	assert(data.getHistoricValue(3) == 3.3);
	assert(data.getHistoricValue(4) == 2.2);
	assert(data.getHistoricValue(5) == 1.1);
#ifdef	STATISTIC_OF_HISTORY_ONLY
	assert(data.getAverage() == Near(23.1/6));
#else
	assert(data.getAverage() == Near(23.1/7));
#endif

	data.setValue(7.7);
	assert(data.size() == 6);
	assert(data.getValue() == 7.7);
	assert(data.getHistoricValue(0) == 7.7);
	assert(data.getHistoricValue(1) == 6.6);
	assert(data.getHistoricValue(2) == 5.5);
	assert(data.getHistoricValue(3) == 4.4);
	assert(data.getHistoricValue(4) == 3.3);
	assert(data.getHistoricValue(5) == 2.2);
#ifdef	STATISTIC_OF_HISTORY_ONLY
	assert(data.getAverage() == Near(29.7/6));
#else
	assert(data.getAverage() == Near(30.8/8));
#endif

	data.clearHistory();
	assert(data.size() == 1);
	assert(data.getValue() == 7.7);
	assert(data.getHistoricValue(0) == 7.7);
#ifdef	STATISTIC_OF_HISTORY_ONLY
	assert(data.getAverage() == Near(7.7/1));
#else
	assert(data.getAverage() == 30.8/8);
#endif

	std::cout << "ALL TESTS PASSED" << std::endl;
}
Example #23
0
int main() {
	Statistic data(0.0);

	assert(data.historySize() == 1);
	assert(data.maxHistory() == 6);
	assert(data.getHistoricValue(0) == 0.0);
	assert(data.getAverage() == 0.0);
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 0.0);

	data.setValue(1.1);
	assert(data.historySize() == 2);
	assert(data.getValue() == 1.1);
	assert(data.getHistoricValue(0) == 1.1);
	assert(data.getHistoricValue(1) == 0.0);
	assert(data.getAverage() == Near(1.1/2));
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 1.1);

	data.setValue(2.2);
	assert(data.historySize() == 3);
	assert(data.getValue() == 2.2);
	assert(data.getHistoricValue(0) == 2.2);
	assert(data.getHistoricValue(1) == 1.1);
	assert(data.getHistoricValue(2) == 0.0);
	assert(data.getAverage() == Near(3.3/3));
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 2.2);

	data.setValue(3.3);
	assert(data.historySize() == 4);
	assert(data.getValue() == 3.3);
	assert(data.getHistoricValue(0) == 3.3);
	assert(data.getHistoricValue(1) == 2.2);
	assert(data.getHistoricValue(2) == 1.1);
	assert(data.getHistoricValue(3) == 0.0);
	assert(data.getAverage() == Near(6.6/4));
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 3.3);

	data.setValue(4.4);
	assert(data.historySize() == 5);
	assert(data.getValue() == 4.4);
	assert(data.getHistoricValue(0) == 4.4);
	assert(data.getHistoricValue(1) == 3.3);
	assert(data.getHistoricValue(2) == 2.2);
	assert(data.getHistoricValue(3) == 1.1);
	assert(data.getHistoricValue(4) == 0.0);
	assert(data.getAverage() == Near(11.0/5));
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 4.4);

	data.setValue(5.5);
	assert(data.historySize() == 6);
	assert(data.getValue() == 5.5);
	assert(data.getHistoricValue(0) == 5.5);
	assert(data.getHistoricValue(1) == 4.4);
	assert(data.getHistoricValue(2) == 3.3);
	assert(data.getHistoricValue(3) == 2.2);
	assert(data.getHistoricValue(4) == 1.1);
	assert(data.getHistoricValue(5) == 0.0);
	assert(data.getAverage() == Near(16.5/6));
	assert(data.getMinimum() == 0.0);
	assert(data.getMaximum() == 5.5);

	data.setValue(6.6);
	assert(data.historySize() == 6);
	assert(data.getValue() == 6.6);
	assert(data.getHistoricValue(0) == 6.6);
	assert(data.getHistoricValue(1) == 5.5);
	assert(data.getHistoricValue(2) == 4.4);
	assert(data.getHistoricValue(3) == 3.3);
	assert(data.getHistoricValue(4) == 2.2);
	assert(data.getHistoricValue(5) == 1.1);
	assert(data.getAverage() == Near(23.1/6));
	assert(data.getMinimum() == 1.1);
	assert(data.getMaximum() == 6.6);

	data.setValue(-.7);
	assert(data.historySize() == 6);
	assert(data.getValue() == -.7);
	assert(data.getHistoricValue(0) == -.7);
	assert(data.getHistoricValue(1) == 6.6);
	assert(data.getHistoricValue(2) == 5.5);
	assert(data.getHistoricValue(3) == 4.4);
	assert(data.getHistoricValue(4) == 3.3);
	assert(data.getHistoricValue(5) == 2.2);
	assert(data.getAverage() == Near(21.3/6));
	assert(data.getMinimum() == -.7);
	assert(data.getMaximum() == 6.6);

	data.clearHistory();
	assert(data.historySize() == 1);
	assert(data.getValue() == -.7);
	assert(data.getHistoricValue(0) == -.7);
	assert(data.getAverage() == Near(-.7/1));
	assert(data.getMinimum() == -.7);
	assert(data.getMaximum() == -.7);

	std::cout << "ALL TESTS PASSED" << std::endl;
}
Example #24
0
bool Near(Position one, Position two, int distance = 1)
{
	return (Near(one.x, two.x, distance) && Near(one.y, two.y, distance));
}
Example #25
0
Node *Best3OptMove(Node * t1, Node * t2, GainType * G0, GainType * Gain)
{
    Node *t3, *t4, *t5, *t6, *T3 = 0, *T4 = 0, *T5 = 0, *T6 = 0;
    Candidate *Nt2, *Nt4;
    GainType G1, G2, G3, G4, BestG4 = MINUS_INFINITY;
    int Case6, BestCase6 = 0, X4, X6;
    int Breadth2 = 0, Breadth4;

    if (SUC(t1) != t2)
        Reversed ^= 1;

    /* 
     * Determine (T3,T4,T5,T6) = (t3,t4,t5,t6)
     * such that 
     *
     *     G4 = *G0 - C(t2,T3) + C(T3,T4) 
     *              - C(T4,T5) + C(T5,T6)
     *
     *  is maximum (= BestG4), and (T5,T6) has not previously been included.
     *  If during this process a legal move with *Gain > 0 is found, then make
     *  the move and exit Best3OptMove immediately. 
     */

    /* 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 && GainCriterionUsed &&
             ProblemType != HCP && ProblemType != HPP))
            continue;
        if (++Breadth2 > MaxBreadth)
            break;
        /* Choose t4 as one of t3's two neighbors on the tour */
        for (X4 = 1; X4 <= 2; X4++) {
            t4 = X4 == 1 ? PRED(t3) : SUC(t3);
            if (FixedOrCommon(t3, t4))
                continue;
            G2 = G1 + C(t3, t4);
            if (X4 == 1 &&
                !Forbidden(t4, t1) &&
                (!c || G2 - c(t4, t1) > 0) && (*Gain = G2 - C(t4, t1)) > 0)
            {
                Swap1(t1, t2, t3);
                return 0;
            }
            if (Backtracking && !Excludable(t3, t4))
                continue;
            Breadth4 = 0;
            /* Choose (t4,t5) as a candidate edge emanating from t4 */
            for (Nt4 = t4->CandidateSet; (t5 = Nt4->To); Nt4++) {
                if (t5 == t4->Pred || t5 == t4->Suc ||
                    ((G3 = G2 - Nt4->Cost) <= 0 && GainCriterionUsed) ||
                    (X4 == 2 && !BETWEEN(t2, t5, t3)))
                    continue;
                if (++Breadth4 > MaxBreadth)
                    break;
                /* Choose t6 as one of t5's two neighbors on the tour */
                for (X6 = 1; X6 <= X4; X6++) {
                    if (X4 == 1) {
                        Case6 = 1 + !BETWEEN(t2, t5, t4);
                        t6 = Case6 == 1 ? SUC(t5) : PRED(t5);
                    } else {
                        Case6 = 4 + X6;
                        t6 = X6 == 1 ? SUC(t5) : PRED(t5);
                        if (t6 == t1)
                            continue;
                    }
                    if (FixedOrCommon(t5, t6))
                        continue;
                    G4 = G3 + C(t5, t6);
                    if (!Forbidden(t6, t1) &&
                        (!c || G4 - c(t6, t1) > 0) &&
                        (*Gain = G4 - C(t6, t1)) > 0) {
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        return 0;
                    }
                    if (GainCriterionUsed && G4 - Precision < t6->Cost)
                        continue;
                    if (!Backtracking || Swaps > 0) {
                        if (G4 > BestG4 &&
                            Swaps < MaxSwaps &&
                            Excludable(t5, t6) &&
                            (!InInputTour(t5, t6) || !Near(t5, t6))) {
                            /* Ignore the move if the gain does not vary */
                            if (RestrictedSearch &&
                                ProblemType != HCP &&
                                ProblemType != HPP &&
                                G2 - t4->Pi == G4 - t6->Pi &&
                                G3 + t5->Pi == G1 + t3->Pi)
                                continue;
                            T3 = t3;
                            T4 = t4;
                            T5 = t5;
                            T6 = t6;
                            BestCase6 = Case6;
                            BestG4 = G4;
                        }
                    } else if (MaxSwaps > 0) {
                        GainType G = G4;
                        Node *t = t6;
                        Make3OptMove(t1, t2, t3, t4, t5, t6, Case6);
                        Exclude(t1, t2);
                        Exclude(t3, t4);
                        Exclude(t5, t6);
                        while ((t = BestSubsequentMove(t1, t, &G, Gain)));
                        if (*Gain > 0)
                            return 0;
                        RestoreTour();
                        if (t2 != SUC(t1))
                            Reversed ^= 1;
                    }
                }
            }
        }
    }
    *Gain = 0;
    if (T6) {
        /* Make the best 3-opt move */
        Make3OptMove(t1, t2, T3, T4, T5, T6, BestCase6);
        Exclude(t1, t2);
        Exclude(T3, T4);
        Exclude(T5, T6);
        *G0 = BestG4;
    }
    return T6;
}