Search code examples
arraysmemoryfortransigabrt

How to remove random rows from a matrix in Fortran90


OK so here is the problem. In my assignment I should create a (3,1000) matrix and after I created it I should delete RANDOMLY 271 rows of the matrix. At the end I should obtain a (3,729) Matrix with all the initial values except the one I deleted corresponding to the random numbers.

To do so I wrote this script where Mc=1000 N=729

h=1
do a=1, (Mc-N)

   call random_number(rand_num)
   rand_num=int(rand_num*Mc)-1
   !print*, rand_num

   do b=1, Mc

      if (b /= rand_num) then

      NMatrix(:,h) = Matrix(:,b)

      h=h+1

      else

      h=h

      endif
    enddo
enddo

But when I run it it reports me this error: Program receiver signal SIGABRT : Process abort signal. What should I do? Please it's really important

I know there is some problem with the do loops and the memory of the arrays, but I cannot get to the point. Can you please ask me?


Solution

  • Here an example ouput of what you are asking for (I think).

    rows=3, cols=1000
    1.000 2.000 3.000 4.000 5.000 6.000 7.000 8.000 9.000 10.00 11.00 12.00 ...
    1001. 1002. 1003. 1004. 1005. 1006. 1007. 1008. 1009. 1010. 1011. 1012. ...
    2001. 2002. 2003. 2004. 2005. 2006. 2007. 2008. 2009. 2010. 2011. 2012. ...
    
    rows=3, cols=729
    1.000 3.000 4.000 9.000 10.00 11.00 12.00 13.00 14.00 16.00 17.00 19.00 ...
    1001. 1003. 1004. 1009. 1010. 1011. 1012. 1013. 1014. 1016. 1017. 1019. ...
    2001. 2003. 2004. 2009. 2010. 2011. 2012. 2013. 2014. 2016. 2017. 2019. ...
    

    Note that by convention, the 1st index is the rows, and the 2nd index is the columns. So you are asking to remove 271 columns from the matrix.

    I decided to use an array of index values indx=[1,2,3,4 .. n], which I shuffle randomly, then slice off the last 271 values (keep n entries) and then sort back to increasing order.

    Finally, the result is essentially NMatrix(:,:) = Matrix(:, indx) or in my case I call them a and b in my function.

    function RemoveRandomColumns(a,n_col) result(b)
    real, intent(in) :: a(:,:)
    integer, intent(in) :: n_col
    real, allocatable :: b(:,:)
    integer :: i,j,n,m,t
    integer, allocatable :: indx(:)
    real :: u !used in shuffle part
    m = size(a, 1)
    n = size(a, 2)
    ! must remove m-n_col columns from a
    allocate(indx(n))
    indx = [ (i,i=1,n) ]
    ! indx = [1,2,3,4,5,6,7,8,..,n]
    
    ! suffle the index
    call RANDOM_SEED()
    do i=1, n
        call RANDOM_NUMBER(u)
        j = 1 + floor(u*(n-1))
        t = indx(i)
        indx(i) = indx(j)
        indx(j) = t
    end do
    ! indx = [18,10,3,16,21,...]
    
    ! take only n_col items
    indx = indx(1:n_col)
    ! indx = [18,10,3,...]
    
    ! sort the index
    do i=1, n_col
        do j=1, i-1
            if(indx(i)<indx(j)) then
                t = indx(i)
                indx(i) = indx(j)
                indx(j) = t
            end if
        end do
    end do
    ! indx = [2,3,4,6,7,9,..,n]
    
    ! now slice the array to get the resukt
    allocate(b(m,n_col))
    do j=1, m
        b(j,:) = a(j,indx)
    end do
    end function
    

    and the sample code to test the above is

    program FortranProgram1
    use, intrinsic :: iso_fortran_env
    implicit none
    
    integer, parameter :: Mc = 1000, n = 729
    
    ! Variables
    real :: matrix(3, Mc)
    real :: reduced(3, n)
    integer :: i,j
    
    do j=1, 3
        do i=1, Mc
            matrix(j,i) = real(Mc*(j-1)+i)
        end do
    end do
    
    print '("rows=",g0,", cols=",g0)', size(matrix,1), size(matrix,2)
    print '(*(g0.4," "))', matrix(1,1:12), "..."
    print '(*(g0.4," "))', matrix(2,1:12), "..."
    print '(*(g0.4," "))', matrix(3,1:12), "..."
    
    print *, ""
    
    reduced = RemoveRandomColumns(matrix, n)
    
    print '("rows=",g0,", cols=",g0)', size(reduced,1), size(reduced,2)
    print '(*(g0.4," "))', reduced(1,1:12), "..."
    print '(*(g0.4," "))', reduced(2,1:12), "..."
    print '(*(g0.4," "))', reduced(3,1:12), "..."
    
    contains
    
    function RemoveRandomColumns(a,n_col) result(b)
    ...
    end function
    
    end program