⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdtree2.f90

📁 kd tree java implementation 2
💻 F90
📖 第 1 页 / 共 4 页
字号:
!!(c) Matthew Kennel, Institute for Nonlinear Science (2004)!! Licensed under the Academic Free License version 1.1 found in file LICENSE! with additional provisions found in that same file.!module kdtree2_precision_module    integer, parameter :: sp = kind(0.0)  integer, parameter :: dp = kind(0.0d0)  private :: sp, dp  !  ! You must comment out exactly one  ! of the two lines.  If you comment  ! out kdkind = sp then you get single precision  ! and if you comment out kdkind = dp   ! you get double precision.  !  integer, parameter :: kdkind = sp    !integer, parameter :: kdkind = dp    public :: kdkindend module kdtree2_precision_modulemodule kdtree2_priority_queue_module  use kdtree2_precision_module  !  ! maintain a priority queue (PQ) of data, pairs of 'priority/payload',   ! implemented with a binary heap.  This is the type, and the 'dis' field  ! is the priority.  !  type kdtree2_result      ! a pair of distances, indexes      real(kdkind)    :: dis!=0.0      integer :: idx!=-1   Initializers cause some bugs in compilers.  end type kdtree2_result  !  ! A heap-based priority queue lets one efficiently implement the following  ! operations, each in log(N) time, as opposed to linear time.  !  ! 1)  add a datum (push a datum onto the queue, increasing its length)   ! 2)  return the priority value of the maximum priority element   ! 3)  pop-off (and delete) the element with the maximum priority, decreasing  !     the size of the queue.   ! 4)  replace the datum with the maximum priority with a supplied datum  !     (of either higher or lower priority), maintaining the size of the  !     queue.   !  !  ! In the k-d tree case, the 'priority' is the square distance of a point in  ! the data set to a reference point.   The goal is to keep the smallest M  ! distances to a reference point.  The tree algorithm searches terminal  ! nodes to decide whether to add points under consideration.  !  ! A priority queue is useful here because it lets one quickly return the  ! largest distance currently existing in the list.  If a new candidate  ! distance is smaller than this, then the new candidate ought to replace  ! the old candidate.  In priority queue terms, this means removing the  ! highest priority element, and inserting the new one.  !  ! Algorithms based on Cormen, Leiserson, Rivest, _Introduction  ! to Algorithms_, 1990, with further optimization by the author.  !  ! Originally informed by a C implementation by Sriranga Veeraraghavan.  !  ! This module is not written in the most clear way, but is implemented such  ! for speed, as it its operations will be called many times during searches  ! of large numbers of neighbors.  !  type pq      !      ! The priority queue consists of elements      ! priority(1:heap_size), with associated payload(:).      !      ! There are heap_size active elements.       ! Assumes the allocation is always sufficient.  Will NOT increase it      ! to match.      integer :: heap_size = 0      type(kdtree2_result), pointer :: elems(:)   end type pq  public :: kdtree2_result  public :: pq  public :: pq_create  public :: pq_delete, pq_insert  public :: pq_extract_max, pq_max, pq_replace_max, pq_maxpri  privatecontains  function pq_create(results_in) result(res)    !    ! Create a priority queue from ALREADY allocated    ! array pointers for storage.  NOTE! It will NOT    ! add any alements to the heap, i.e. any existing    ! data in the input arrays will NOT be used and may    ! be overwritten.    !     ! usage:    !    real(kdkind), pointer :: x(:)    !    integer, pointer :: k(:)    !    allocate(x(1000),k(1000))    !    pq => pq_create(x,k)    !    type(kdtree2_result), target:: results_in(:)     type(pq) :: res    !    !    integer :: nalloc    nalloc = size(results_in,1)    if (nalloc .lt. 1) then       write (*,*) 'PQ_CREATE: error, input arrays must be allocated.'    end if    res%elems => results_in    res%heap_size = 0    return  end function pq_create  !  ! operations for getting parents and left + right children  ! of elements in a binary heap.  !!! These are written inline for speed.!    !  integer function parent(i)!    integer, intent(in) :: i!    parent = (i/2)!    return!  end function parent!  integer function left(i)!    integer, intent(in) ::i!    left = (2*i)!    return!  end function left!  integer function right(i)!    integer, intent(in) :: i!    right = (2*i)+1!    return!  end function right!  logical function compare_priority(p1,p2)!    real(kdkind), intent(in) :: p1, p2!!    compare_priority = (p1 .gt. p2)!    return!  end function compare_priority  subroutine heapify(a,i_in)    !    ! take a heap rooted at 'i' and force it to be in the    ! heap canonical form.   This is performance critical     ! and has been tweaked a little to reflect this.    !    type(pq),pointer   :: a    integer, intent(in) :: i_in    !    integer :: i, l, r, largest    real(kdkind)    :: pri_i, pri_l, pri_r, pri_largest    type(kdtree2_result) :: temp    i = i_inbigloop:  do       l = 2*i ! left(i)       r = l+1 ! right(i)       !        ! set 'largest' to the index of either i, l, r       ! depending on whose priority is largest.       !       ! note that l or r can be larger than the heap size       ! in which case they do not count.       ! does left child have higher priority?        if (l .gt. a%heap_size) then          ! we know that i is the largest as both l and r are invalid.          exit        else          pri_i = a%elems(i)%dis          pri_l = a%elems(l)%dis           if (pri_l .gt. pri_i) then             largest = l             pri_largest = pri_l          else             largest = i             pri_largest = pri_i          endif          !          ! between i and l we have a winner          ! now choose between that and r.          !          if (r .le. a%heap_size) then             pri_r = a%elems(r)%dis             if (pri_r .gt. pri_largest) then                largest = r             endif          endif       endif       if (largest .ne. i) then          ! swap data in nodes largest and i, then heapify          temp = a%elems(i)          a%elems(i) = a%elems(largest)          a%elems(largest) = temp           !           ! Canonical heapify() algorithm has tail-ecursive call:           !          !        call heapify(a,largest)             ! we will simulate with cycle          !          i = largest          cycle bigloop ! continue the loop        else          return   ! break from the loop       end if    enddo bigloop    return  end subroutine heapify  subroutine pq_max(a,e)     !    ! return the priority and its payload of the maximum priority element    ! on the queue, which should be the first one, if it is     ! in heapified form.    !    type(pq),pointer :: a    type(kdtree2_result),intent(out)  :: e    if (a%heap_size .gt. 0) then       e = a%elems(1)     else       write (*,*) 'PQ_MAX: ERROR, heap_size < 1'       stop    endif    return  end subroutine pq_max    real(kdkind) function pq_maxpri(a)    type(pq), pointer :: a    if (a%heap_size .gt. 0) then       pq_maxpri = a%elems(1)%dis    else       write (*,*) 'PQ_MAX_PRI: ERROR, heapsize < 1'       stop    endif    return  end function pq_maxpri  subroutine pq_extract_max(a,e)    !    ! return the priority and payload of maximum priority    ! element, and remove it from the queue.    ! (equivalent to 'pop()' on a stack)    !    type(pq),pointer :: a    type(kdtree2_result), intent(out) :: e        if (a%heap_size .ge. 1) then       !       ! return max as first element       !       e = a%elems(1)               !       ! move last element to first       !       a%elems(1) = a%elems(a%heap_size)        a%heap_size = a%heap_size-1       call heapify(a,1)       return    else       write (*,*) 'PQ_EXTRACT_MAX: error, attempted to pop non-positive PQ'       stop    end if      end subroutine pq_extract_max  real(kdkind) function pq_insert(a,dis,idx)     !    ! Insert a new element and return the new maximum priority,    ! which may or may not be the same as the old maximum priority.    !    type(pq),pointer  :: a    real(kdkind), intent(in) :: dis    integer, intent(in) :: idx    !    type(kdtree2_result), intent(in) :: e    !    integer :: i, isparent    real(kdkind)    :: parentdis    !    !    if (a%heap_size .ge. a%max_elems) then    !       write (*,*) 'PQ_INSERT: error, attempt made to insert element on full PQ'    !       stop    !    else    a%heap_size = a%heap_size + 1    i = a%heap_size    do while (i .gt. 1)       isparent = int(i/2)       parentdis = a%elems(isparent)%dis       if (dis .gt. parentdis) then          ! move what was in i's parent into i.          a%elems(i)%dis = parentdis          a%elems(i)%idx = a%elems(isparent)%idx          i = isparent       else          exit       endif    end do    ! insert the element at the determined position    a%elems(i)%dis = dis    a%elems(i)%idx = idx    pq_insert = a%elems(1)%dis     return    !    end if  end function pq_insert  subroutine pq_adjust_heap(a,i)    type(pq),pointer  :: a    integer, intent(in) :: i    !    ! nominally arguments (a,i), but specialize for a=1    !    ! This routine assumes that the trees with roots 2 and 3 are already heaps, i.e.    ! the children of '1' are heaps.  When the procedure is completed, the    ! tree rooted at 1 is a heap.    real(kdkind) :: prichild    integer :: parent, child, N    type(kdtree2_result) :: e    e = a%elems(i)     parent = i    child = 2*i    N = a%heap_size        do while (child .le. N)       if (child .lt. N) then          if (a%elems(child)%dis .lt. a%elems(child+1)%dis) then             child = child+1          endif       endif       prichild = a%elems(child)%dis       if (e%dis .ge. prichild) then          exit        else          ! move child into parent.          a%elems(parent) = a%elems(child)           parent = child          child = 2*parent       end if    end do    a%elems(parent) = e    return  end subroutine pq_adjust_heap      real(kdkind) function pq_replace_max(a,dis,idx)     !    ! Replace the extant maximum priority element    ! in the PQ with (dis,idx).  Return    ! the new maximum priority, which may be larger    ! or smaller than the old one.    !    type(pq),pointer         :: a    real(kdkind), intent(in) :: dis    integer, intent(in) :: idx!    type(kdtree2_result), intent(in) :: e    ! not tested as well!    integer :: parent, child, N    real(kdkind)    :: prichild, prichildp1    type(kdtree2_result) :: etmp        if (.true.) then       N=a%heap_size       if (N .ge. 1) then          parent =1          child=2          loop: do while (child .le. N)             prichild = a%elems(child)%dis             !             ! posibly child+1 has higher priority, and if             ! so, get it, and increment child.             !             if (child .lt. N) then                prichildp1 = a%elems(child+1)%dis                if (prichild .lt. prichildp1) then                   child = child+1                   prichild = prichildp1                endif             endif             if (dis .ge. prichild) then                exit loop                  ! we have a proper place for our new element,                 ! bigger than either children's priority.             else                ! move child into parent.                a%elems(parent) = a%elems(child)                 parent = child                child = 2*parent             end if          end do loop          a%elems(parent)%dis = dis          a%elems(parent)%idx = idx          pq_replace_max = a%elems(1)%dis       else          a%elems(1)%dis = dis          a%elems(1)%idx = idx          pq_replace_max = dis       endif    else       !       ! slower version using elementary pop and push operations.       !       call pq_extract_max(a,etmp)        etmp%dis = dis       etmp%idx = idx       pq_replace_max = pq_insert(a,dis,idx)    endif    return  end function pq_replace_max  subroutine pq_delete(a,i)    !     ! delete item with index 'i'    !    type(pq),pointer :: a    integer           :: i    if ((i .lt. 1) .or. (i .gt. a%heap_size)) then       write (*,*) 'PQ_DELETE: error, attempt to remove out of bounds element.'       stop    endif    ! swap the item to be deleted with the last element    ! and shorten heap by one.    a%elems(i) = a%elems(a%heap_size)     a%heap_size = a%heap_size - 1    call heapify(a,i)  end subroutine pq_deleteend module kdtree2_priority_queue_modulemodule kdtree2_module  use kdtree2_precision_module

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -