Option Explicit

 

' Optimised Carraghan, R., Pardalos, P. M.

' by using a heuristic vertex colouring and a backtrack search

 

Private moClasses() As Long, mnClassesCount As Long

Private level_nodes() As Long, nStart() As Long, NodesNum() As Long ' number of nodes on level

Private t As Long, mnMaxClique As Long

Private nLevelWAcc() As Long

Private nLevelDegree() As Long

Private nMaxCliques() As Long

'

 

Public Function Start() As Long

  Dim i As Long, t_minus_1 As Long, nn As Long, wt As Long

 

  ReDim level_nodes(1 To Nodes, 1 To Nodes, 0 To 1)

  ReDim nMaxCliques(1 To Nodes)

  '''''' each level has its own set of nodes

  For i = 1 To Nodes

    level_nodes(1, i, 0) = i

  Next

  '''''''''''''''''''''''''''''''''''

  DefineClasses

  ResortByWeights

  For i = 1 To Nodes

    level_nodes(1, i, 1) = i

  Next

  ReDim NodesNum(1 To mnClassesCount)

  ReDim nStart(1 To mnClassesCount)

  ReDim nLevelDegree(1 To mnClassesCount)

  ReDim nLevelWAcc(1 To mnClassesCount)

  NodesNum(1) = Nodes

 

  For nn = Nodes To 1 Step -1

    t = 2

    NodesNum(t) = 0

    nLevelWAcc(t) = w(level_nodes(1, nn, 0))

    For i = nn + 1 To Nodes

      If arr(level_nodes(1, nn, 0), level_nodes(1, i, 0)) Then

        NodesNum(t) = NodesNum(t) + 1

        level_nodes(t, NodesNum(t), 0) = level_nodes(1, i, 0)

        level_nodes(t, NodesNum(t), 1) = level_nodes(1, i, 1)

      End If

    Next

    If NodesNum(t) = 0 Then

      t = t - 1

      If nLevelWAcc(t + 1) > mnMaxClique Then

        mnMaxClique = nLevelWAcc(t + 1)

      End If

    Else

      nStart(t) = 0

    End If

   

    While t >= 2

      nStart(t) = nStart(t) + 1

           

      If NodesNum(t) < nStart(t) Then

        t = t - 1

      Else

        If (nLevelWAcc(t) + nMaxCliques(level_nodes(t, nStart(t), 1))) > _

           mnMaxClique Then

     

          If nStart(t) > 1 Then

            If (moClasses(level_nodes(t, nStart(t), 0)) <> _

                            moClasses(level_nodes(t, nStart(t) - 1, 0))) Then

                 nLevelDegree(t) = nLevelDegree(t) - w(level_nodes(t, nStart(t) - 1, 0))

            Else

                 nLevelDegree(t) = nLevelDegree(t) - w(level_nodes(t, nStart(t) - 1, 0)) _

                     + w(level_nodes(t, nStart(t), 0))

            End If

          Else

            ''' calculate degree on new depth

            nLevelDegree(t) = LevelDegree()

          End If

       

          If (nLevelWAcc(t) + nLevelDegree(t)) > mnMaxClique Then

            t_minus_1 = t

            t = t + 1

            nStart(t) = 0

            NodesNum(t) = 0

            nLevelWAcc(t) = nLevelWAcc(t_minus_1) + _

                    w(level_nodes(t_minus_1, nStart(t_minus_1), 0))

            ''' define nodes for the next level

            For i = nStart(t_minus_1) + 1 To NodesNum(t_minus_1)

              If arr(level_nodes(t_minus_1, nStart(t_minus_1), 0), _

                     level_nodes(t_minus_1, i, 0)) Then

                NodesNum(t) = NodesNum(t) + 1

                level_nodes(t, NodesNum(t), 0) = level_nodes(t_minus_1, i, 0)

                level_nodes(t, NodesNum(t), 1) = level_nodes(t_minus_1, i, 1)

              End If

            Next

            If NodesNum(t) = 0 Then

              t = t - 1

              If nLevelWAcc(t + 1) > mnMaxClique Then

                mnMaxClique = nLevelWAcc(t + 1)

              End If

            End If

          Else

            t = t - 1

          End If

        Else

          t = t - 1

        End If

      End If

    Wend

    nMaxCliques(nn) = mnMaxClique

  Next

 

  ''' return size of maximu clique

  Start = mnMaxClique

End Function

 

Private Sub DefineClasses()

  Dim class_init() As Boolean '' show if node exists

  Dim i As Long, k As Long

  Dim mnRemainNodes As Long, bFirstNode As Boolean, nkNode As Long

  Dim nNodeNum As Long

 

  mnClassesCount = 0

  ReDim class_init(1 To Nodes)

  ''' get info about existing nodes

  ReDim moClasses(1 To Nodes)

  '''''

  mnRemainNodes = Nodes

  While True

    ''' build up new class

    mnClassesCount = mnClassesCount + 1

    bFirstNode = True

    ''' position of first node

    i = mnRemainNodes

    While i > 0

      ''' swap nodes

      nNodeNum = level_nodes(1, i, 0)

      If i <> mnRemainNodes Then

        ''' swap rows

        level_nodes(1, i, 0) = level_nodes(1, mnRemainNodes, 0)

        level_nodes(1, mnRemainNodes, 0) = nNodeNum

      End If

      '''

      moClasses(nNodeNum) = mnClassesCount

     

      mnRemainNodes = mnRemainNodes - 1

      If mnRemainNodes = 0 Then Exit Sub

      If bFirstNode Then

        For k = 1 To mnRemainNodes

          nkNode = level_nodes(1, k, 0)

          class_init(nkNode) = arr(nNodeNum, nkNode)

        Next

      Else

        For k = 1 To mnRemainNodes

          nkNode = level_nodes(1, k, 0)

          class_init(nkNode) = arr(nNodeNum, nkNode) Or class_init(nkNode)

        Next

      End If

      bFirstNode = False

      For i = mnRemainNodes To 1 Step -1

        If Not class_init(level_nodes(1, i, 0)) Then Exit For

      Next

    Wend

  Wend

End Sub

 

Private Function LevelDegree() As Long

  Dim res As Long, i As Long, nClass As Long, aClass As Long

 

    For i = NodesNum(t) To nStart(t) Step -1

      ''' for node on level define class (moClasses) and mark it as existing

      nClass = moClasses(level_nodes(t, i, 0))

      If nClass <> aClass Then

        res = res + w(level_nodes(t, i, 0))

        aClass = nClass

      End If

    Next

 

  LevelDegree = res

 

End Function

 

Public Sub ResortByWeights()

  Dim i As Long, j As Long, maxi As Long, maxw As Long, aClass As Long

  Dim nNode As Long

  For i = Nodes To 2 Step -1

    maxi = i

    nNode = level_nodes(1, maxi, 0)

    maxw = w(nNode)

    aClass = moClasses(nNode)

    For j = i - 1 To 1 Step -1

      nNode = level_nodes(1, j, 0)

      If moClasses(nNode) <> aClass Then Exit For

      If maxw < w(nNode) Then

        maxi = j

        maxw = w(nNode)

      End If

    Next

    If i <> maxi Then

      nNode = level_nodes(1, i, 0)

      level_nodes(1, i, 0) = level_nodes(1, maxi, 0)

      level_nodes(1, maxi, 0) = nNode

    End If

  Next

End Sub