How to remove random rows from a matrix in Fortran90

88 views Asked by At

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?

1

There are 1 answers

0
John Alexiou On BEST ANSWER

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