program basis_to_flat
implicit none
integer(8) i,j,k,l,n,m,nb,rk,binom,rkmin,rkmax,tmax,y,t,non
integer(8),parameter::param = 500
integer(8) s(param),b(param),c(param,param),d(param),e(param,param),f(param,param,param),nf(param,param,param),g(param,param),h(param,param),sr(param)
logical(1) loopless,t1,t2,z
write(*,*)'マトロイドの基底とフラットを無作為に生成します。'
write(*,*)'試行回数の上限?'
write(*,*)'注:31以下に設定してください。'
read(*,*)t
tmax = 2**t - 2
write(*,*)'台集合の元の個数?'
read(*,*)n
write(*,*)'ループなしにする? T or F'
read(*,*)loopless
write(*,*)'階数の最小値を設ける? T or F'
read(*,*)t1
if(t1 .eqv. .true.) then
write(*,*)'最小値?'
read(*,*)rkmin
endif
write(*,*)'階数の最大値を設ける? T or F'
read(*,*)t2
if (t2 .eqv. .true.) then
write(*,*)'最大値?'
read(*,*)rkmax
endif
m = 2**n
y = 0
if (m > param) y = y + 1
if (m > param) goto 13
call genbase_unlim_sub(rk,nb,b,n,loopless,t1,t2,rkmin,rkmax,tmax,z)
if (z .eqv. .false.) goto 14
s(1) = 0
do i= 2,m
s(i) = s(i-1) + 1
end do
do i= 1,m
do j=1,nb
c(i,j) = iand(s(i),b(j))
enddo
enddo
do i=1,m
do j=1,nb
h(i,j)=0
enddo
enddo
do i=1,m
do j=1,nb
do l=1,n
if (iand(c(i,j),2**(l-1)) == 2**(l-1)) h(i,j) = h(i,j)+1
enddo
enddo
enddo
do i=1,m
sr(i)=0
enddo
do i=1,m
do j=1,nb
if (sr(i) <= h(i,j)) sr(i) = h(i,j)
enddo
enddo
non = -1
do i=1,m
d(i)= ieor(non,s(i))
end do
do i=1,m
do k=1,n
if (iand(d(i),2**(k-1)) == 2**(k-1)) e(i,k) = s(i)+2**(k-1)
if (iand(d(i),2**(k-1)) /= 2**(k-1)) e(i,k) = 0
enddo
enddo
do i = 1,m
do j=1,nb
do k=1,n
f(i,j,k) = iand(e(i,k),b(j))
enddo
enddo
enddo
do i = 1,m
do j=1,nb
do k=1,n
nf(i,j,k) = 0
enddo
enddo
enddo
do i = 1,m
do j=1,nb
do k=1,n
do l=1,n
if (iand(f(i,j,k),2**(l-1)) == 2**(l-1)) nf(i,j,k) = nf(i,j,k) + 1
enddo
enddo
enddo
enddo
do i = 1, m
do k = 1, n
g(i,k) = 0
enddo
enddo
do i=1,m
do j=1,nb
do k=1,n
if (g(i,k) <= nf(i,j,k)) g(i,k) = nf(i,j,k)
enddo
enddo
enddo
do i=1,m
do k=1,n
if (g(i,k) == sr(i)) s(i) = -1
enddo
enddo
do i = 0, rk
print'(A6,I3)','rank =',i
do j = 1, m
if ((sr(j) == i) .and. (s(j) /= -1)) print'(b8.8)',s(j)
enddo
enddo
13 if (y == 1) print*,'台集合が大きすぎます。'
14 continue
end program basis_to_flat
subroutine genbase_unlim_sub(rk,nb,s,n,loopless,t1,t2,rkmin,rkmax,tmax,z)
implicit none
integer(8) n,m,t,rk,tmax,nb,nbmin,nbmax,rkmin,rkmax,i,j,k,l,h,d,d1,d2,u
integer(8),parameter:: param = 500
integer(8) s(param),ns(param)
integer(8) factorial,binom
logical(1) z,t1,t2,loopless,c
real x
z = .false.
m = 2*n
do t = 1, tmax
call random_number(x)
nb = int(x*binom(n,n/2)) + 1
if (nb > param) cycle
do i = 1, nb
call random_number(x)
s(i) = int(x*(2**n))
enddo
do i = 1, nb
do j = 1, nb
if (i == j) cycle
if (s(i) == s(j)) goto 10
enddo
enddo
if (loopless .eqv. .true.) then
u = s(1)
do i = 2, nb
u = ior(u,s(i))
enddo
if (u /= 2**n-1) goto 10
endif
do i = 1, nb
ns(i) = 0
enddo
do i = 1, nb
do j = 1, n
if (iand(s(i),2**(j-1)) == 2**(j-1)) ns(i) = ns(i) + 1
enddo
enddo
do i = 1, nb
do j = 1, nb
if (ns(i) /= ns(j)) goto 10
enddo
enddo
if ((t1 .eqv. .true.) .and. (ns(1) < rkmin)) goto 10
if ((t2 .eqv. .true.) .and. (ns(1) > rkmax)) goto 10
do i = 1, nb
do j = 1, nb
if (i == j) cycle
d = ieor(s(i),s(j))
d1 = iand(d,s(i))
d2 = iand(d,s(j))
do k = 1, n
if (iand(d1,2**(k-1)) /= 2**(k-1)) cycle
c = .false.
do l = 1, n
if (iand(d2,2**(l-1)) /= 2**(l-1)) cycle
do h = 1, nb
if ((s(i) - 2**(k-1)) + 2**(l-1) == s(h)) c = .true.
enddo
enddo
if (c .eqv. .false.) goto 10
enddo
enddo
enddo
z = .true.
exit
10 enddo
do i = 1, nb
print'(b32.32)',s(i)
enddo
rk = ns(1)
if (z .eqv. .true.) print'(A6,I32)','階数 = ',rk
print'(A6,I32)','試行回数 = ',t
if (z .eqv. .true.) print'(A6)','成功'
if (z .eqv. .false.) print'(A6)','失敗'
end subroutine genbase_unlim_sub
function binom(n,k)
implicit none
integer(8) binom,n,k,i
if (n-k > k) k = n-k
binom = n
do i = n-1, k + 1,-1
binom = binom * i
enddo
do i = 1, n-k
binom = binom / i
enddo
end function binom