Advertisement
Guest User

Untitled

a guest
Mar 18th, 2016
381
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Fortran 42.32 KB | None | 0 0
  1. !  RUBIK.f90
  2. !
  3. !  FUNCTIONS:
  4. !   RUBIK      - Entry point of console application.
  5. !
  6. !
  7.  
  8. !****************************************************************************
  9. !
  10. !  PROGRAM: RUBIK
  11. !
  12. !
  13. !****************************************************************************
  14.  
  15. module external_fcts
  16. implicit none
  17.  
  18. integer  :: m, n, o
  19.  
  20. contains
  21.  
  22.     subroutine ToString(sequence_numbers, numbersToString)
  23.  
  24.         integer, dimension(:), intent(in)   :: sequence_numbers
  25.         integer                             :: a, taille_sequence
  26.         character, dimension(:),intent(out) :: numbersToString
  27.         taille_sequence = size(sequence_numbers)
  28.        
  29.  
  30.         do a = 1, taille_sequence
  31.             select case(mod(sequence_numbers(a),6))
  32.                 case(0)
  33.                     numbersToString(3*a-2) = 'F'
  34.                 case(1)
  35.                     numbersToString(3*a-2) = 'U'
  36.                 case(2)
  37.                     numbersToString(3*a-2) = 'R'
  38.                 case(3)
  39.                     numbersToString(3*a-2) = 'B'
  40.                 case(4)
  41.                     numbersToString(3*a-2) = 'D'
  42.                 case(5)
  43.                     numbersToString(3*a-2) = 'L'
  44.             end select
  45.            
  46.             numbersToString(3*a-1) = ' '
  47.             if (sequence_numbers(a)> 5) numbersToString(3*a-1) = '2'
  48.             if (sequence_numbers(a)>11) numbersToString(3*a-1) = "'"
  49.             numbersToString(3*a) = ' '
  50.         end do
  51.  
  52.     end subroutine ToString
  53.  
  54.     subroutine ToNumbers(sequence_string, StringToNumbers)
  55.         character, dimension(2), intent(in)     :: sequence_string
  56.         integer, intent(out)                    :: StringToNumbers
  57.         integer                                 :: a, b, taille_string
  58.  
  59.         do a=1, 2
  60.             select case(sequence_string(a))
  61.                 case('F')
  62.                     StringToNumbers = 0
  63.                 case('U')
  64.                     StringToNumbers = 1
  65.                 case('R')
  66.                     StringToNumbers = 2
  67.                 case('B')
  68.                     StringToNumbers = 3
  69.                 case('D')
  70.                     StringToNumbers = 4
  71.                 case('L')
  72.                     StringToNumbers = 5
  73.                 case("2")
  74.                     StringToNumbers = StringToNumbers+6
  75.                 case("'")
  76.                     StringToNumbers = StringToNumbers+12
  77.                 !case default
  78.                 !   print*, 'Incorrect caracter. Exit and run the program again'
  79.  
  80.             end select
  81.         end do
  82.         !print*, StringToNumbers
  83.  
  84.     end subroutine ToNumbers
  85.  
  86.     function init(cube)
  87.         integer, dimension(0:53), intent(in)  :: cube
  88.         integer, dimension(0:53)              :: init
  89.         integer                               :: indice = 0, temp = 0
  90.        
  91.         do m = 0, 5
  92.             do n = 0, 8
  93.             init(indice) = temp
  94.             indice = indice+1
  95.             end do
  96.             temp = temp+1
  97.         end do
  98.  
  99.     return
  100.     end function init
  101.  
  102.  
  103.     function do_move(cube_state, move)
  104.         integer, dimension(0:53), intent(in) :: cube_state
  105.         integer, dimension(0:53)             :: do_move, cube
  106.         integer, intent(in)                  :: move
  107.         integer                              :: repetition
  108.        
  109.         do_move = cube_state
  110.        
  111.        
  112.         repetition = 0
  113.         if(move > 5)   repetition = 1
  114.         if(move > 11)  repetition = 2
  115.         if(move > 17)  repetition = 3  !stupide, c'est un tour complet (juste pour test)
  116.  
  117.         do m = 0, repetition
  118.         cube = do_move         
  119.  
  120.         !tourne les cubes de la face en question
  121.         do_move = turn_face(do_move, mod(move,6))  
  122.        
  123.         !tourne ceux de la couronne
  124.         select case(mod(move,6))
  125.         case(0)
  126.             do_move(15) = cube(53)
  127.             do_move(16) = cube(50)
  128.             do_move(17) = cube(47)
  129.             do_move(18) = cube(15)
  130.             do_move(21) = cube(16)
  131.             do_move(24) = cube(17)
  132.             do_move(36) = cube(24)
  133.             do_move(37) = cube(21)
  134.             do_move(38) = cube(18)
  135.             do_move(47) = cube(36)
  136.             do_move(50) = cube(37)
  137.             do_move(53) = cube(38)
  138.         case(1)
  139.             do_move(0) = cube(18)
  140.             do_move(1) = cube(19)
  141.             do_move(2) = cube(20)
  142.             do_move(18) = cube(27)
  143.             do_move(19) = cube(28)
  144.             do_move(20) = cube(29)
  145.             do_move(27) = cube(45)
  146.             do_move(28) = cube(46)
  147.             do_move(29) = cube(47)
  148.             do_move(45) = cube(0)
  149.             do_move(46) = cube(1)
  150.             do_move(47) = cube(2)
  151.         case(2)
  152.             do_move(2) = cube(38)
  153.             do_move(5) = cube(41)
  154.             do_move(8) = cube(44)
  155.             do_move(11) = cube(2)
  156.             do_move(14) = cube(5)
  157.             do_move(17) = cube(8)
  158.             do_move(27) = cube(17)
  159.             do_move(30) = cube(14)
  160.             do_move(33) = cube(11)
  161.             do_move(38) = cube(33)
  162.             do_move(41) = cube(30)
  163.             do_move(44) = cube(27)
  164.         case(3)
  165.             do_move(9) = cube(20)
  166.             do_move(10) = cube(23)
  167.             do_move(11) = cube(26)
  168.             do_move(20) = cube(44)
  169.             do_move(23) = cube(43)
  170.             do_move(26) = cube(42)
  171.             do_move(42) = cube(45)
  172.             do_move(43) = cube(48)
  173.             do_move(44) = cube(51)
  174.             do_move(45) = cube(11)
  175.             do_move(48) = cube(10)
  176.             do_move(51) = cube(9)
  177.         case(4)
  178.             do_move(6) = cube(51)
  179.             do_move(7) = cube(52)
  180.             do_move(8) = cube(53)
  181.             do_move(24) = cube(6)
  182.             do_move(25) = cube(7)
  183.             do_move(26) = cube(8)
  184.             do_move(33) = cube(24)
  185.             do_move(34) = cube(25)
  186.             do_move(35) = cube(26)
  187.             do_move(51) = cube(33)
  188.             do_move(52) = cube(34)
  189.             do_move(53) = cube(35)
  190.         case(5)
  191.             do_move(0) = cube(9)
  192.             do_move(3) = cube(12)
  193.             do_move(6) = cube(15)
  194.             do_move(9) = cube(35)
  195.             do_move(12) = cube(32)
  196.             do_move(15) = cube(29)
  197.             do_move(29) = cube(42)
  198.             do_move(32) = cube(39)
  199.             do_move(35) = cube(36)
  200.             do_move(36) = cube(0)
  201.             do_move(39) = cube(3)
  202.             do_move(42) = cube(6)
  203.         case default
  204.             print*, "move error"
  205.         end select
  206.  
  207.         end do
  208.         return
  209.     end function do_move
  210.  
  211.     function turn_face(cube, face)
  212.        
  213.         integer, dimension(0:53), intent(in) :: cube
  214.         integer, dimension(0:53)             :: turn_face
  215.         integer, intent(in)                  :: face
  216.         integer                              :: offset
  217.        
  218.         turn_face = cube
  219.         offset = 9*face
  220.  
  221.         turn_face(mod(offset,54)) = cube(mod(offset+6,54))
  222.         turn_face(mod(offset+1,54)) = cube(mod(offset+3,54))
  223.         turn_face(mod(offset+2,54)) = cube(mod(offset+0,54))
  224.         turn_face(mod(offset+3,54)) = cube(mod(offset+7,54))
  225.         turn_face(mod(offset+5,54)) = cube(mod(offset+1,54))
  226.         turn_face(mod(offset+6,54)) = cube(mod(offset+8,54))
  227.         turn_face(mod(offset+7,54)) = cube(mod(offset+5,54))
  228.         turn_face(mod(offset+8,54)) = cube(mod(offset+2,54))
  229.  
  230.     end function turn_face
  231.  
  232.     subroutine print_cube(cube)
  233.         integer, intent(in), dimension(0:53)  :: cube
  234.         integer                               :: offset
  235.  
  236.         offset = 0
  237.         do m = 0, 5
  238.             print*, cube(0+offset:8+offset)
  239.             offset = offset+9
  240.         end do
  241.  
  242.     end subroutine print_cube
  243.  
  244.     function compare(cube1, cube2)
  245.         integer, dimension(0:53), intent(in) :: cube1, cube2
  246.         integer                              :: compare
  247.            
  248.         compare = 0
  249.         do m = 0, 53
  250.             if(cube1(m) == cube2(m)) compare = compare +1
  251.             if(cube2(m) > 5) then
  252.                 if (cube1(m) < 6) compare = compare+1  !sticker = 6=> couleur pas importante
  253.             end if
  254.         end do
  255.     end function compare
  256.  
  257.     function do_sequence(cube, move_sequence, sequence_size)
  258.         integer, intent(in)                  :: sequence_size
  259.         integer, dimension(0:53), intent(in) :: cube
  260.         integer, dimension(sequence_size), intent(in)    :: move_sequence
  261.         integer, dimension(0:53)             :: do_sequence
  262.        
  263.         do_sequence = do_move(cube, move_sequence(1)) !initialisation
  264.        
  265.         if(sequence_size > 1) then
  266.             do n = 2, sequence_size
  267.                 do_sequence = do_move(do_sequence, move_sequence(n))
  268.             end do
  269.         end if
  270.        
  271.     end function do_sequence
  272.  
  273.         function entropy(cube)
  274.         !calcule l'entropie du cube, définie comme (somme(CEP) + somme(ECeP))
  275.         !CEP = corner-edge pairs
  276.         !ECeP = edges-center pairs
  277.         !Ouaiiii c'est pas la vrai entropie puisque je la maximise ;)
  278.  
  279.         integer, dimension(0:53), intent(in)    :: cube
  280.         integer                                 :: entropy
  281.        
  282.         entropy = 0
  283.        
  284.         !Corner-edges pairs
  285.         !FLU corner
  286.         if(cube(0) == cube(1) .and. cube(15)== cube(16)) entropy = entropy+1
  287.         if(cube(0) == cube(3) .and. cube(47)== cube(50)) entropy = entropy+1
  288.         if(cube(47) == cube(46) .and. cube(15) == cube(12)) entropy = entropy+1
  289.         !FRU corner
  290.         if(cube(2) == cube(5) .and. cube(18)== cube(21)) entropy = entropy+1
  291.         if(cube(2) == cube(1) .and. cube(17)== cube(16)) entropy = entropy+1
  292.         if(cube(17) == cube(14) .and. cube(18) == cube(19)) entropy = entropy+1
  293.         !FRD corner
  294.         if(cube(8) == cube(5) .and. cube(24)== cube(21)) entropy = entropy+1
  295.         if(cube(8) == cube(7) .and. cube(38)== cube(37)) entropy = entropy+1
  296.         if(cube(38) == cube(41) .and. cube(24) == cube(25)) entropy = entropy+1
  297.         !FLD corner
  298.         if(cube(6) == cube(3) .and. cube(53)== cube(50)) entropy = entropy+1
  299.         if(cube(6) == cube(7) .and. cube(36)== cube(37)) entropy = entropy+1
  300.         if(cube(36) == cube(39) .and. cube(53) == cube(52)) entropy = entropy+1
  301.         !BLU corner
  302.         if(cube(29) == cube(32) .and. cube(45)== cube(48)) entropy = entropy+1
  303.         if(cube(29) == cube(28) .and. cube(9)== cube(10)) entropy = entropy+1
  304.         if(cube(9) == cube(12) .and. cube(45) == cube(46)) entropy = entropy+1
  305.         !BRU corner
  306.         if(cube(27) == cube(28) .and. cube(11)== cube(10)) entropy = entropy+1
  307.         if(cube(27) == cube(30) .and. cube(20)== cube(23)) entropy = entropy+1
  308.         if(cube(11) == cube(14) .and. cube(20) == cube(19)) entropy = entropy+1
  309.         !BRD corner
  310.         if(cube(33) == cube(34) .and. cube(44)== cube(43)) entropy = entropy+1
  311.         if(cube(33) == cube(30) .and. cube(26)== cube(23)) entropy = entropy+1
  312.         if(cube(44) == cube(41) .and. cube(26) == cube(25)) entropy = entropy+1
  313.         !BLD corner
  314.         if(cube(35) == cube(34) .and. cube(42)== cube(43)) entropy = entropy+1
  315.         if(cube(35) == cube(32) .and. cube(51)== cube(48)) entropy = entropy+1
  316.         if(cube(42) == cube(39) .and. cube(51) == cube(52)) entropy = entropy+1
  317.  
  318.  
  319.         !Edges-centers pairs
  320.         !F
  321.         if(cube(4) == cube(1))  entropy = entropy+1
  322.         if(cube(4) == cube(3))  entropy = entropy+1
  323.         if(cube(4) == cube(5))  entropy = entropy+1
  324.         if(cube(4) == cube(7))  entropy = entropy+1
  325.         !U
  326.         if(cube(13) == cube(10))  entropy = entropy+1
  327.         if(cube(13) == cube(12))  entropy = entropy+1
  328.         if(cube(13) == cube(14))  entropy = entropy+1
  329.         if(cube(13) == cube(16))  entropy = entropy+1
  330.         !R
  331.         if(cube(22) == cube(19))  entropy = entropy+1
  332.         if(cube(22) == cube(21))  entropy = entropy+1
  333.         if(cube(22) == cube(23))  entropy = entropy+1
  334.         if(cube(22) == cube(25))  entropy = entropy+1
  335.         !B
  336.         if(cube(31) == cube(28))  entropy = entropy+1
  337.         if(cube(31) == cube(30))  entropy = entropy+1
  338.         if(cube(31) == cube(32))  entropy = entropy+1
  339.         if(cube(31) == cube(34))  entropy = entropy+1
  340.         !D
  341.         if(cube(40) == cube(37))  entropy = entropy+1
  342.         if(cube(40) == cube(39))  entropy = entropy+1
  343.         if(cube(40) == cube(41))  entropy = entropy+1
  344.         if(cube(40) == cube(43))  entropy = entropy+1
  345.         !L
  346.         if(cube(49) == cube(46))  entropy = entropy+1
  347.         if(cube(49) == cube(48))  entropy = entropy+1
  348.         if(cube(49) == cube(50))  entropy = entropy+1
  349.         if(cube(49) == cube(52))  entropy = entropy+1
  350.  
  351.     end function entropy
  352.  
  353.     function is2x2x3(cube)
  354.         !Voir commentaires fonction entropy ...
  355.         !fonction "vérifiant" l'état du 2x2x3 situé en BD en terme de CE et ECe pairs
  356.         !vaut 16 ssi le 2x2x3 est complet
  357.  
  358.         integer, dimension(0:53), intent(in)    :: cube
  359.         integer                                 :: is2x2x3
  360.        
  361.         is2x2x3 = 0
  362.        
  363.         !Corner-edges pairs
  364.         !BRD corner
  365.         if(cube(33) == cube(34) .and. cube(44)== cube(43)) is2x2x3 = is2x2x3+1
  366.         if(cube(33) == cube(30) .and. cube(26)== cube(23)) is2x2x3 = is2x2x3+1
  367.         if(cube(44) == cube(41) .and. cube(26) == cube(25)) is2x2x3 = is2x2x3+1
  368.         !BLD corner
  369.         if(cube(35) == cube(34) .and. cube(42)== cube(43)) is2x2x3 = is2x2x3+1
  370.         if(cube(35) == cube(32) .and. cube(51)== cube(48)) is2x2x3 = is2x2x3+1
  371.         if(cube(42) == cube(39) .and. cube(51) == cube(52)) is2x2x3 = is2x2x3+1
  372.  
  373.         !Edges-centers pairs
  374.         !R
  375.         !if(cube(22) == cube(19))  is2x2x3 = is2x2x3+1
  376.         !if(cube(22) == cube(21))  is2x2x3 = is2x2x3+1
  377.         if(cube(22) == cube(23))  is2x2x3 = is2x2x3+1
  378.         if(cube(22) == cube(25))  is2x2x3 = is2x2x3+1
  379.         !B
  380.         !if(cube(31) == cube(28))  is2x2x3 = is2x2x3+1
  381.         if(cube(31) == cube(30))  is2x2x3 = is2x2x3+1
  382.         if(cube(31) == cube(32))  is2x2x3 = is2x2x3+1
  383.         if(cube(31) == cube(34))  is2x2x3 = is2x2x3+1
  384.         !D
  385.         !if(cube(40) == cube(37))  is2x2x3 = is2x2x3+1
  386.         if(cube(40) == cube(39))  is2x2x3 = is2x2x3+1
  387.         if(cube(40) == cube(41))  is2x2x3 = is2x2x3+1
  388.         if(cube(40) == cube(43))  is2x2x3 = is2x2x3+1
  389.         !L
  390.         !if(cube(49) == cube(46))  is2x2x3 = is2x2x3+1
  391.         if(cube(49) == cube(48))  is2x2x3 = is2x2x3+1
  392.         !if(cube(49) == cube(50))  is2x2x3 = is2x2x3+1
  393.         if(cube(49) == cube(52))  is2x2x3 = is2x2x3+1
  394.  
  395.     end function is2x2x3
  396.  
  397.     function is2gen(cube)
  398.         !checks if a given cube is 2-gen solvable, according to two rules :
  399.         !   correct edges orientation
  400.         !   solvable position of corners (according to Sebastian Dumitrescu's demonstration)
  401.         !   two different corners linkages must be computed !
  402.         !   returns 1 if OK, 0 otherwise
  403.  
  404.         !The given 2 faces are F & U
  405.  
  406.         use dflib
  407.  
  408.         integer, dimension(0:53), intent(in)    :: cube
  409.         integer                                 :: is2gen
  410.         integer, dimension(6)                   :: corners_pos
  411.         integer, dimension(6)                   :: corner_temp
  412.         integer                                 :: edges_ori, co
  413.  
  414.         is2gen = 0
  415.         edges_ori = 0
  416.  
  417.         !checks the orientation of edges
  418.         if(cube(1) == cube(4) .or. cube(16) == cube(13)) edges_ori = edges_ori+1
  419.         if(cube(3) == cube(4) .or. cube(50) == cube(13)) edges_ori = edges_ori+1
  420.         if(cube(5) == cube(4) .or. cube(21) == cube(13)) edges_ori = edges_ori+1
  421.         if(cube(7) == cube(4) .or. cube(37) == cube(13)) edges_ori = edges_ori+1
  422.         if(cube(28) == cube(4) .or. cube(10) == cube(13)) edges_ori = edges_ori+1
  423.         if(cube(46) == cube(4) .or. cube(13) == cube(13)) edges_ori = edges_ori+1
  424.         if(cube(19) == cube(4) .or. cube(14) == cube(13)) edges_ori = edges_ori+1
  425.        
  426.         if (edges_ori < 7) return
  427.  
  428.         !corners :
  429.         !5  6  U face
  430.         !3  4
  431.         !1  2  F face
  432.         !checks the position of the corners: 1st test (link 5-1, 6-2, 3-4 and observe the pattern)
  433.         corner_temp(1) = 2**cube(6)+ 2**cube(36)+2**cube(53) !FDL positioned corner of cube
  434.         corner_temp(2) = 2**cube(8)+2**cube(38)+2**cube(24)  !FDR
  435.         corner_temp(3) = 2**cube(0)+2**cube(15)+2**cube(47)  !FUL
  436.         corner_temp(4) = 2**cube(2)+2**cube(17)+2**cube(18)  !FUR      
  437.         corner_temp(5) = 2**cube(29)+2**cube(9)+2**cube(45)  !BUL
  438.         corner_temp(6) = 2**cube(27)+2**cube(11)+2**cube(20) !BUR
  439.        
  440.         do co = 1, 6
  441.             if (corner_temp(co) == 2**cube(4)+2**cube(40)+2**cube(49)) corners_pos(co)=0
  442.             if (corner_temp(co) == 2**cube(4)+2**cube(40)+2**cube(22)) corners_pos(co)=1
  443.             if (corner_temp(co) == 2**cube(4)+2**cube(13)+2**cube(49)) corners_pos(co)=2
  444.             if (corner_temp(co) == 2**cube(4)+2**cube(13)+2**cube(22)) corners_pos(co)=2
  445.             if (corner_temp(co) == 2**cube(31)+2**cube(13)+2**cube(49)) corners_pos(co)=0
  446.             if (corner_temp(co) == 2**cube(31)+2**cube(13)+2**cube(22)) corners_pos(co)=1
  447.         end do
  448.  
  449.         !print*, "corners positions", corners_pos
  450.        
  451.         !on doit passer en scalaire pour le select case
  452.         co = 100000*corners_pos(1)+10000*corners_pos(2)+1000*corners_pos(3)+100*corners_pos(4)+10*corners_pos(5)+corners_pos(6)
  453.         select case(co)
  454.             case(12201,1221,11022,12120,10212,102210,110220,100122,102021,101202,210021,221001,211200,210102,212010,21102,2112,22011,21210,20121,120012,112002,122100,120201,121020,201120,220110,200211,201012,202101)
  455.                 is2gen = 1
  456.             case default
  457.                 return
  458.         end select
  459.  
  460.         !2nd test (link 5-2, 6-4, 3-1 and observe the pattern)
  461.                 do co = 1, 6
  462.             if (corner_temp(co) == 2**cube(4)+2**cube(40)+2**cube(49)) corners_pos(co)=0
  463.             if (corner_temp(co) == 2**cube(4)+2**cube(40)+2**cube(22)) corners_pos(co)=1
  464.             if (corner_temp(co) == 2**cube(4)+2**cube(13)+2**cube(49)) corners_pos(co)=0
  465.             if (corner_temp(co) == 2**cube(4)+2**cube(13)+2**cube(22)) corners_pos(co)=2
  466.             if (corner_temp(co) == 2**cube(31)+2**cube(13)+2**cube(49)) corners_pos(co)=1
  467.             if (corner_temp(co) == 2**cube(31)+2**cube(13)+2**cube(22)) corners_pos(co)=2
  468.         end do
  469.  
  470.         !print*, "corners positions", corners_pos
  471.        
  472.         !on doit passer en scalaire pour le select case
  473.         co = 100000*corners_pos(1)+10000*corners_pos(2)+1000*corners_pos(3)+100*corners_pos(4)+10*corners_pos(5)+corners_pos(6)
  474.         select case(co)
  475.             case(12201,1221,11022,12120,10212,102210,110220,100122,102021,101202,210021,221001,211200,210102,212010,21102,2112,22011,21210,20121,120012,112002,122100,120201,121020,201120,220110,200211,201012,202101)
  476.                 is2gen = 1
  477.             case default
  478.                 is2gen = 0
  479.         end select
  480.  
  481.    
  482.     end function is2gen
  483.  
  484.     function fobj(cube, cube_solved, moves_sequence, sequence_size, type_func )
  485.         !La fonction objectif est définie comme nmax - x, où nmax est le nombre max de stickers OK
  486.         !en parcourant la séquence de moves et x le nombre de mouvements après lesquels on y arrive
  487.         !Exemple d'appel :
  488.         !print*, fobj(cube_scrambled, cube_solved, moves_sequence, size(moves_sequence),1)
  489.  
  490.         integer, intent(in)                             :: sequence_size, type_func
  491.         integer, dimension(0:53), intent(in)            :: cube, cube_solved
  492.         integer, dimension(sequence_size), intent(in)   :: moves_sequence
  493.         integer, dimension(2)                           :: fobj
  494.         integer     :: nmax, x, ni, i
  495.         integer, dimension(0:53)                        :: cube_temp
  496.        
  497.         cube_temp = cube
  498.        
  499.         x = 0
  500.         nmax = 0                                    !approche par paires
  501.  
  502.         !nmax = compare(cube_temp, cube_solved)  !approche par stickers
  503.         if (sequence_size > 1) then
  504.             do i = 1, sequence_size
  505.                 cube_temp = do_move(cube_temp, moves_sequence(i))
  506.  
  507.                 select case(type_func)
  508.                 case (1)
  509.                     ni = compare(cube_temp, cube_solved)            !Approche par stickers
  510.                 case (2)
  511.                     ni = entropy(cube_temp)                         !Approche par paires
  512.                 case (3)
  513.                     ni = is2x2x3(cube_temp)                         !Approche par 2x2x3 en BD
  514.                 case (4)
  515.                     ni = 10*is2gen(cube_temp) + 10*is2x2x3(cube_temp)   !Phase getting into 2-gen
  516.                 end select
  517.  
  518.                 if (ni > nmax) then
  519.                     nmax = ni
  520.                     x = i
  521.                 end if
  522.                 !print*, i ,ni, nmax, x
  523.             end do
  524.         end if
  525.  
  526.         fobj(1) = 10*nmax -x
  527.         fobj(2) = x
  528.  
  529.     end function fobj
  530.  
  531.     subroutine solve_twogen_bourrin(cube_2gen, cube_solved)
  532.     !résoud un cube dans le groupe twogen de manière optimale (HTM)
  533.     integer, dimension(0:53), intent(in)    :: cube_2gen, cube_solved
  534.     integer, dimension(0:24)                :: sol
  535.     integer, dimension(3)                   :: m
  536.     integer, dimension(2)                   :: test_resolu
  537.     integer                                 :: m1,m2,m3
  538.    
  539.     sol=sol+3   !On remplit la sol du 2-gen avec des mouvements qui n'ont rien à y faire (initialisation
  540.  
  541.  
  542.     do m1=0,5
  543.         sol(0)=(m1/2)*6 + mod(m1,2)  !0,1,6,7,12,13 OK
  544.         !print*, mod(m1,2), " sol(0) : ", sol(0)
  545.         test_resolu = fobj(cube_2gen, cube_solved, sol, 25, 1)
  546.         !print*, (test_resolu(1)+test_resolu(2))/10.
  547.         if((test_resolu(1)+test_resolu(2))/10. == 54) then
  548.             print*, "youpie 1 !"
  549.             print*, sol
  550.             GOTO 3001
  551.         end if
  552.        
  553.         do m2=0,5 !C'est pas top, ainsi il ajoute  de toute façon #m mouvements, changer les boucles...
  554.             sol(1)=(m2/2)*6 + mod(m2,2)  !0,1,6,7,12,13 OK
  555.             test_resolu = fobj(cube_2gen, cube_solved, sol, 25, 1)
  556.             if((test_resolu(1)+test_resolu(2))/10. == 54) then
  557.                 print*, "youpie 2 !"
  558.                 print*, sol
  559.                 GOTO 3001
  560.             end if
  561.         end do
  562.    
  563.     end do
  564.  
  565.    
  566. 3001    end subroutine solve_twogen_bourrin
  567.  
  568.  
  569.  
  570.     function classement_population(pop, val_fobj)
  571.     !classe une population selon les valeurs décroissantes de la fonction objectif
  572.    
  573.     integer, dimension(:, :), intent(in)    :: pop
  574.     integer, dimension(:)                   :: val_fobj   !seulement la valeur de fobj
  575.     integer                                 :: max_indice, taille, i
  576.     integer, dimension(size(pop, 1), size(pop,2))   :: classement_population
  577.  
  578.     taille = size(pop, 1)
  579.  
  580.     classement_population = pop
  581.  
  582.     do i = 1, taille
  583.         max_indice = maxloc(val_fobj,1)
  584.         classement_population(i,:) = pop(max_indice, :)
  585.         val_fobj(max_indice) = -10000
  586.     end do
  587.  
  588.     end function classement_population
  589.  
  590.     function pop_mariee (pop, phi, pc, perfo)
  591. !Choisit des couples parmi une population d'individus triés par ordre de fobj croissante:
  592. !pc = probabilité de croisement
  593. !n = taille population
  594. !phi = nbre moyen de descendants de l'Elite
  595.  
  596.     use dflib
  597.     use dfport
  598.  
  599.     integer, dimension(:,:), intent(in)             :: pop
  600.     integer, dimension(size(pop,1),2), intent(in)   :: perfo
  601.     real, intent(in)                                :: phi, pc
  602.     integer, dimension(size(pop,1),size(pop,2))     :: pop_mariee
  603.     real, dimension(0:size(pop,1)-1)                :: pi
  604.     integer                                         :: i, j, n, numero_enf, r0, p1, p2, cross
  605.     real                                            :: x0, y0
  606.    
  607.     call seed(RND$TIMESEED)
  608.     n = size(pop, 1)
  609.  
  610.     !pop2 se remplira avec les enfants
  611.     pop_mariee = pop
  612.  
  613.     !Calcul de la proba du nombre d'enfants en fct du rang
  614.  
  615.     do i = 0, n-1
  616.  
  617.         pi(i) = 1./n * (phi - i*(2.*phi-2)/(n-1.))    
  618.     end do
  619.  
  620.     !Stratégie élitiste : on conserve l'Elite -> boucle start @ numero_enf = 2 et génère (n-1)/2 couples
  621.  
  622.     numero_enf = 2
  623.     do j = 1, (n-1)/2
  624.  
  625.         !Choix du premier parent :
  626.     1   call random(x0)
  627.         r0 = int(n*0.9999*x0)            !le 0.9999 c'est pour si jamais x0==1
  628.         call random(y0)
  629.  
  630.         if( (2. - phi + 2.*y0*(phi-1.))/n > pi(r0)) then
  631.             GOTO 1
  632.         end if
  633.  
  634.         p1 = r0+1
  635.  
  636.         !Choix du 2e parent : aléatoire équiprobable
  637.  
  638.         call random(x0)
  639.         p2=int(n*0.9999*x0)+1
  640.  
  641.         !print*, p1, p2
  642.  
  643.         !Choix du gène de cross-over appartient à {1, ..., long_code-1}
  644.         !ALEATOIRE
  645.         call random(x0)
  646.         cross = (size(pop,2)-1) * 0.9999* x0 + 1   !pour le cas foireux ou x0 ==1 pile
  647.         !OU : APRES LE 1ER MAX DE FOBJ pour le premier parent
  648.         !cross = perfo(p1, 2)
  649.  
  650.         if (cross == size(pop,2)) cross = cross-1
  651.         !On attribue les gênes 1:cross du premier parent à l'individu numero_enf et cross+1:fin du 2e parent
  652.         !vice-versa à l'individu suivant (son frère)
  653.         !croisement a lieu avec une proba pc
  654.  
  655.         call random(x0)
  656.  
  657.         if(x0 < pc) then
  658.         pop_mariee(numero_enf, 1:cross) = pop(p1, 1:cross)
  659.         pop_mariee(numero_enf, cross+1:size(pop,2)) = pop(p2, cross+1:size(pop,2))
  660.         pop_mariee(numero_enf+1, 1:cross) = pop(p2, 1:cross)
  661.         pop_mariee(numero_enf+1, cross+1:size(pop,2)) = pop(p1, cross+1:size(pop,2))
  662.        
  663.         else  !pas croisement
  664.         pop_mariee(numero_enf, :)   = pop(p1, :)
  665.         pop_mariee(numero_enf+1, :) = pop(p2, :)
  666.  
  667.         end if
  668.  
  669.         numero_enf =numero_enf + 2
  670.  
  671.     end do   !boucle j sur le remplissage de pop2
  672.  
  673.     end function pop_mariee
  674.  
  675.     function pop_mutee(pop, pm)
  676.  
  677.         use dflib
  678.         use dfport
  679.  
  680.         integer, dimension(:,:), intent(in)             :: pop
  681.         real, intent(in)                                :: pm
  682.         integer, dimension(size(pop,1),size(pop,2))     :: pop_mutee
  683.         integer                                         :: i, j, n1, n2, g0
  684.         real                                            :: x0
  685.        
  686.         call seed(RND$TIMESEED)
  687.         n1 = size(pop, 1)
  688.         n2 = size(pop, 2)
  689.  
  690.         pop_mutee = pop
  691.  
  692.         do i = 2, n1  !elite ne mute pas !
  693.          do j = 1, n2
  694.             call random(x0)
  695.             if (x0 < pm) then
  696.                 call random(x0)
  697.                 g0 = 18*0.9999*x0
  698.                 pop_mutee(i,j) = g0
  699.             end if
  700.          end do
  701.         end do
  702.  
  703.  
  704.     end function pop_mutee
  705.  
  706.     function trim_sequence (moves_sequence)
  707.  
  708.         use dflib
  709.         use dfport
  710.  
  711.         integer, dimension(:), intent(in)           :: moves_sequence
  712.         integer, dimension(size(moves_sequence))    :: trim_sequence
  713.         integer :: l, ltot, shoots, move, move_suivant
  714.         real    :: r
  715.        
  716.         call seed(RND$TIMESEED)
  717.  
  718.         ltot = size(moves_sequence)
  719.         trim_sequence = moves_sequence
  720.  
  721.  
  722.         shoots = 0
  723. 21      do l = 1, ltot-1
  724.             move = trim_sequence(l)
  725.             move_suivant = trim_sequence(l+1)
  726.             if(mod(move, 6) == mod(move_suivant, 6)) then
  727.                 if(abs(move-move_suivant)== 12) then !Deux moves s'annulent
  728.                     trim_sequence(l:ltot-2) = trim_sequence(l+2:ltot)
  729.                     do shoots = 1,2
  730.                     call random(r)
  731.                     trim_sequence(ltot-2+shoots) = 18 * 0.9999* r
  732.                     end do
  733.                 end if
  734.  
  735.                 if(move < 6) then  !Face
  736.                     if(move_suivant == move) then ! face puis face = face^2
  737.                         trim_sequence(l) = move+6
  738.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  739.                         call random(r)
  740.                         trim_sequence(ltot) = 18 * 0.9999* r
  741.                     else if(move_suivant == move+6) then ! face puis face^2 = face'                
  742.                         trim_sequence(l) = move+12
  743.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  744.                         call random(r)
  745.                         trim_sequence(ltot) = 18 * 0.9999* r
  746.                     end if
  747.                 end if
  748.                
  749.                 if(move < 12) then
  750.                     if(move<6) GOTO 22
  751.                     if (move_suivant == move-6) then !Face^2 puis face = face'
  752.                         trim_sequence(l) = move+6
  753.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  754.                         call random(r)
  755.                         trim_sequence(ltot) = 18 * 0.9999* r
  756.                     else if (move_suivant == move) then !Face^2 puis face^2 = annule
  757.                         trim_sequence(l:ltot-2) = trim_sequence(l+2:ltot)
  758.                         do shoots = 1,2
  759.                         call random(r)
  760.                         trim_sequence(ltot-2+shoots) = 18 * 0.9999* r
  761.                         end do
  762.                     else if (move_suivant == move+6) then !Face^2 puis face' = face
  763.                         trim_sequence(l) = move-6
  764.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  765.                         call random(r)
  766.                         trim_sequence(ltot) = 18 * 0.9999* r
  767.                     end if
  768.                 end if
  769.                 if (move < 12)  GOTO 22
  770.                 ! Arrive ci-dessous si et seulement move et face'
  771.                 if(move_suivant == move-6)  then !face' puis face^2 = face
  772.                         trim_sequence(l) = move-12
  773.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  774.                         call random(r)
  775.                         trim_sequence(ltot) = 18 * 0.9999* r
  776.                 else if(move_suivant == move) then !face' puis face' = face^2
  777.                         trim_sequence(l) = move-6
  778.                         trim_sequence(l+1:ltot-1) = trim_sequence(l+2:ltot)
  779.                         call random(r)
  780.                         trim_sequence(ltot) = 18 * 0.9999* r
  781.                 end if
  782. 22          GO TO 21  ! Juste pour avoir un GO TO
  783.             end if
  784.  
  785.         end do
  786.  
  787. end function trim_sequence
  788.  
  789.     function twist_sequence(moves_sequence)
  790.         !twists moves sequence clockwise around FUR corner
  791.         !vouaiii un peu stupide, autant twister le cube ...
  792.         integer, dimension(:), intent(in)       :: moves_sequence
  793.         integer, dimension(size(moves_sequence)):: twist_sequence
  794.         twist_sequence = 6*(moves_sequence/6) + mod(1+moves_sequence-6*(moves_sequence/6) ,3) + 3*((moves_sequence-6*(moves_sequence/6))/3)
  795.  
  796.     end function twist_sequence
  797.  
  798.     function twist_cube(c)
  799.         !twists whole cube around FUR corner
  800.         integer, dimension(0:53), intent(in)    :: c
  801.         integer, dimension(0:53)                :: twist_cube
  802.        
  803.         !print*, "FUR clockwise twist (= x y)"
  804.         twist_cube(0:8)   = [c(24),c(21),c(18),c(25),c(22),c(19),c(26),c(23),c(20)] !F<-R
  805.         twist_cube(9:17)  = [c(6),c(3),c(0),c(7),c(4),c(1),c(8),c(5),c(2)]          !U<-F
  806.         twist_cube(18:26) = [c(17),c(16),c(15),c(14),c(13),c(12),c(11),c(10),c(9)]  !R<-U
  807.         twist_cube(27:35) = [c(47),c(50),c(53),c(46),c(49),c(52),c(45),c(48),c(51)] !B<-L
  808.         twist_cube(36:44) = [c(33),c(30),c(27),c(34),c(31),c(28),c(35),c(32),c(29)] !D<-B
  809.         twist_cube(45:53) = c(36:44)                                                !L<-D
  810.  
  811.     end function twist_cube
  812.  
  813.     function rotate_whole_cube(cu)
  814.             !rotates whole cube clockwise around vertical axis
  815.         integer, dimension(0:53), intent(in)    :: cu
  816.         integer, dimension(0:53)                :: rotate_whole_cube
  817.        
  818.         !print*, "whole cube clockwise rotation around Oz (= y)"
  819.         rotate_whole_cube(9:17) = [cu(15),cu(12),cu(9),cu(16),cu(13),cu(10),cu(17),cu(14),cu(11)] !U
  820.         rotate_whole_cube(36:44)= [cu(38),cu(41),cu(44),cu(37),cu(40),cu(43),cu(36),cu(39),cu(42)]!D       
  821.         rotate_whole_cube(0:8)   = cu(18:26)        !F<-R
  822.         rotate_whole_cube(18:26) = cu(27:35)        !R<-B
  823.         rotate_whole_cube(27:35) = cu(45:53)        !B<-L
  824.         rotate_whole_cube(45:53) = cu(0:8)          !L<-F
  825.  
  826.     end function rotate_whole_cube
  827.  
  828.     function rotate_whole_cube_x(cu)
  829.             !rotates whole cube clockwise LR axis (= x)
  830.             !defined as xy yyy
  831.  
  832.         integer, dimension(0:53), intent(in)    :: cu
  833.         integer, dimension(0:53)                :: rotate_whole_cube_x
  834.         integer                                 :: rot
  835.                
  836.         !print*, "whole cube clockwise rotation around Oy (= x)"
  837.         rotate_whole_cube_x = cu
  838.  
  839.         rotate_whole_cube_x = twist_cube(cu)
  840.         do rot = 1,3
  841.             rotate_whole_cube_x = rotate_whole_cube(rotate_whole_cube_x)
  842.         end do
  843.  
  844.     end function rotate_whole_cube_x
  845.  
  846.    
  847.  
  848. end module external_fcts
  849.  
  850. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  851. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  852.     program RUBIK
  853.  
  854.  
  855.    
  856.     use external_fcts
  857.     use dflib
  858.     use dfport
  859.  
  860.     implicit none
  861.  
  862.     integer                                 :: i, j, k, ll, lll, two_gen, loc2x2x3, scramble_type, moves_total, twogen_bourrin
  863.     integer, dimension(:), allocatable      :: moves_sequence, scramble_sequence
  864.     integer, dimension(0:53)                :: cube_solved, cube_scrambled, cube, cube_scrambled_copy
  865.     real                                    :: r !random number
  866.     character, dimension(:),allocatable     :: scramble_notation, sequence_notation, sol1, sol2, sol3
  867.     character*2                             :: char_buffer
  868.     integer, dimension(12)                  :: best2x2x3loc, best2x2x3fobj, best2x2x3fobj_copie
  869.     integer, dimension(12, 30)              :: best2x2x3elits
  870.     integer, dimension(12,2)                :: best_temp
  871.    
  872.     !Paramètres algo génétique
  873.     integer                                     :: taille_pop, long_code, Ttot, generation, nbre_intrus, is_continuing
  874.     real                                        :: pm, pc, phi
  875.     integer, dimension(:,:), allocatable        :: pop, perfo, perfo_copie
  876.     integer, dimension(:,:,:), allocatable      :: pop_storage   !si on doit recommencer les 2x2x3, on ne perd pas tout ;-)
  877.  
  878.     !initialisation
  879.     call seed(RND$TIMESEED)   !la seed est effectivement différente à chaque appel :)
  880.     cube_solved = init(cube)
  881.     scramble_type = 2    !0 = défini manuellement, 1 = random, 2 = entré manuellement
  882.    
  883.     print*, 'Genetic rubik''s cube solver, version 2.1'
  884.     print*, ''
  885.     print*, 'Cyril Castella, May 22, 2005'
  886.     print*, 'http://www.francocube.com'
  887.     print*, ''
  888.     print*, 'Enter scramble type : 1 = random, 2 = User-defined'
  889.     read*, scramble_type
  890.     print*, ''
  891.     print*, 'Enter number of generations for simulation : '
  892.     read*, Ttot
  893.  
  894.     two_gen = 0
  895.     twogen_bourrin=0        !résoud le 2-gen par brute force au lieu algo génétique
  896.  
  897.     open(unit=10, file='results.txt', status='replace')
  898.  
  899.     !mélange
  900.  
  901.     allocate(scramble_sequence(37))
  902.     !scramble_sequence = [6,1,14,17,0,1,14,17,0,1,14,17,0,1,14,17,0,9,13,14,10,0,2,9,7,0,2,9,7,0,2,9,7,0,2,9,7,4] !FMC#81, 38 moves
  903.     !scramble_sequence = [14,16,14,6,3,7,17,16,0,7,17,16,0,7,17,16,0,8,1,5,0,7,14,5,9,12,2,10,1,12,2,10,1,12,2,10,1,11,12,15,4] !41 moves
  904.     !scramble_sequence = [0,1,6,13,0,1,6,13,0,1,6,13,6,7,12,1,6,13,0,1,6,13,0,1,6,13,0,7,12,1,6,13,12,7,0,13,12,7,0,13,12,7,0] !43 moves 2-.gen
  905.     !scramble_sequence = [10,14,9,10,17,6,15,10,12,17,6,15,10,12,17,6,15,10,12,13,3,7,15,12,2,12,3,1,10,2,12,3,1,10,2,12,3,1,10,0,1,15,12] !#82, 43 moves
  906.     scramble_sequence = [2,4,2,3,11,4,15,5,0,4,15,5,0,4,15,5,0,8,4,12,7,3,2,16,7,3,2,16,7,3,2,16,11,2,4,7,6] !FMC#83, 37 moves
  907.     !if(two_gen) scramble_sequence = mod(scramble_sequence,2) + 6*(scramble_sequence/6) !2-gen scramble
  908.  
  909.     if(scramble_type == 1) then
  910.         print*, 'Enter number of moves of the scramble'
  911.         read*, j
  912.         deallocate(scramble_sequence)
  913.         allocate(scramble_sequence(j))
  914.         do i = 1, j
  915.             call random(r)
  916.             scramble_sequence(i) = 18*0.9999*r
  917.         end do
  918.         scramble_sequence = trim_sequence(scramble_sequence)
  919.     endif
  920.  
  921.     if(scramble_type ==2) then
  922.         print*, 'Enter number of moves of the scramble'
  923.         read*, j
  924.         print*, 'Enter the scramble moves. Only one move (HTM) per line !'
  925.         deallocate(scramble_sequence)
  926.         allocate(scramble_sequence(j))
  927.         do i = 1, j
  928.             read*, char_buffer
  929.             call ToNumbers(char_buffer, scramble_sequence(i))
  930.         end do
  931.     end if
  932.  
  933.     allocate(scramble_notation(3*size(scramble_sequence)))
  934.     call ToString(scramble_sequence, scramble_notation)
  935.     print*, scramble_notation
  936.  
  937.     !Ecriture du scramble dans le fichier de résultats
  938.     write(10, *), 'Scramble : '
  939.     write(10, *), scramble_notation
  940.  
  941.     cube_scrambled = do_sequence(cube_solved, scramble_sequence, size(scramble_sequence))
  942.     cube_scrambled_copy = cube_scrambled
  943.  
  944.  
  945. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Solving 2x2x3 !!!!!!!!!!!!!!!!!!!!!!!!!!!
  946.  
  947.     is_continuing = 0
  948.     taille_pop = 51     !# individus
  949.     nbre_intrus = 5     !#individus aléatoires remplacent les plus mauvais de pop à chaque gén.
  950.     long_code  = 30     !nombre de gènes  
  951.     !Ttot = 50      !nombre de générations
  952.     pm = 0.05           !proba mutation
  953.     pc = 0.8            !proba croisement
  954.     phi = 1.5           !poids élite
  955.  
  956.     allocate(pop_storage(12, taille_pop, long_code))
  957.     allocate(pop(taille_pop, long_code))
  958.     allocate(perfo(taille_pop, 2))
  959.     allocate(perfo_copie(taille_pop,2))
  960.  
  961. 101 do loc2x2x3 = 0,11
  962.     print*,''
  963.     print*, '------------2x2x3 position is : ', loc2x2x3, '       ----------'
  964.  
  965.     cube_scrambled = cube_scrambled_copy   !subtil ... je crois qu'une de mes fcts change cube_scrambled
  966.  
  967.     !Subtil ... mais visite effectivement toutes les 12 locations possibles ;-)
  968.     ! 0 = BD, 1 = xy = BL, 2 = x2 = FU, 3 = y = DL, 4 = yxy = FL, 5 = yx2 = UR
  969.     ! 6 = y2 = FD, 7 = y2xy = FR, 8 = y2x2 = UB, 9 = y3 = RD, 10 = y3xy = RB, 11 = y3x2UL
  970.  
  971.     do ll=1, loc2x2x3/3
  972.         cube_scrambled = rotate_whole_cube(cube_scrambled)
  973.         print*, "whole cube clockwise rotation around Oz (= y)"
  974.         print*
  975.     end do
  976.  
  977.     select case (modulo(loc2x2x3,3))
  978.         case(1)
  979.             cube_scrambled = twist_cube(cube_scrambled)
  980.             print*, "whole cube rotation around FUR corner (=xy)"
  981.         case(2)
  982.             do i = 1,2
  983.                 cube_scrambled = rotate_whole_cube_x(cube_scrambled)
  984.                 print*, "whole cube rotation around LR horizontal axis (=x)"
  985.             end do
  986.     end select
  987.  
  988.     k = is2gen(cube_scrambled)
  989.     !print*, "... is 2-gen ? ", k
  990.     if(k==1) then
  991.         print*, '2-gen solve'
  992.         two_gen = 1
  993.     end if
  994.    
  995.     !génération population initiale
  996.     do i = 1, taille_pop
  997.         do j = 1, long_code
  998.             call random(r)
  999.             pop(i,j) = r*0.9999*18
  1000.         end do
  1001.     end do
  1002.    
  1003.     !si on est en train de continuer car pas assez de générations, on reprend la pop d'avant pour
  1004.     !cette location
  1005.     if(is_continuing) pop = pop_storage(loc2x2x3+1, :, :)
  1006.  
  1007.     do generation = 1, Ttot
  1008.    
  1009.     if(two_gen) pop = mod(pop,2) + 6*(pop/6)        !2-gen-> séquence contient uniquement (F,U)
  1010.     !Raccourci des mouvements qui s'annulent
  1011.     do i = 1, taille_pop
  1012.         pop(i,:) = trim_sequence(pop(i,:))
  1013.     end do
  1014.    
  1015.     !Evaluation de la fonction objectif sur la population
  1016.     !pour fobj : 3=2x2x3, 4=is2gen, 2=entropy
  1017.     do i = 1, taille_pop
  1018.     perfo(i, :) = fobj(cube_scrambled, cube_solved, pop(i, :), long_code, 3)
  1019.     !print*, pop(i,:), perfo(i, 1)
  1020.     end do
  1021.    
  1022.     !classement de la population
  1023.     perfo_copie = perfo
  1024.     pop = classement_population(pop, perfo_copie(:,1))
  1025.     perfo_copie = perfo
  1026.     perfo = classement_population(perfo, perfo_copie(:,1))  !subtil :)
  1027.  
  1028.     !Print de l'état actuel
  1029.     if (modulo(generation, 100000) == 0) then
  1030.     print*, "Generation / elite/ moy. ", generation, perfo(1,:), float(sum(perfo(:,1))/taille_pop)
  1031.     end if
  1032.  
  1033.     !génocide des nmbre_intrus plus mauvais de la pop et remplacement par des aléatoires
  1034.     if(nbre_intrus > 0) then
  1035.         do i = taille_pop-nbre_intrus+1, taille_pop
  1036.             do j = 1, long_code
  1037.                 call random(r)
  1038.                 pop(i,j) = r*0.9999*18
  1039.             end do
  1040.         end do
  1041.     end if
  1042.  
  1043.     !Mariages
  1044.     pop = pop_mariee (pop, phi, pc, perfo)
  1045.  
  1046.     !mutations
  1047.     pop = pop_mutee (pop, pm)
  1048.  
  1049.  
  1050.     end do  !fin boucle sur les generations
  1051.    
  1052.     pop_storage(loc2x2x3+1, :,:) = pop
  1053.  
  1054.     print*, "optimal :"
  1055.     allocate(sequence_notation(3*perfo(1,2)))
  1056.     call ToString(pop(1,1:perfo(1,2)), sequence_notation)
  1057.     print*, sequence_notation
  1058.     print*, "perfo, # moves, entropy"
  1059.     print*, perfo(1,:), (perfo(1,1)+perfo(1,2))/10
  1060.     if((perfo(1,1)+perfo(1,2))/10==16) print*, 'This 2x2x3 was solved :)'
  1061.     print*,''
  1062.    
  1063.     best2x2x3loc(loc2x2x3+1) = loc2x2x3
  1064.     best2x2x3elits(loc2x2x3+1, :) = pop(1, :)  
  1065.     best2x2x3fobj(loc2x2x3+1) = -perfo(1, 2) - (16-(perfo(1,1)+perfo(1,2))/10)*100 !pénalise une chiée si 2x2x3 pas solved
  1066.    
  1067.     deallocate(sequence_notation)
  1068.     end do !FIN BOUCLE SUR loc2x2x3
  1069.  
  1070. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Getting into 2-gen !!!!!!!!!!!!!!!!!!!!!!!!!!!
  1071.  
  1072.    
  1073.     !Classement des élites en fonction de leur fobj définie ci-dessus
  1074.  
  1075. 200 print*, ''
  1076.     best2x2x3fobj_copie = best2x2x3fobj
  1077.     best2x2x3elits = classement_population(best2x2x3elits, best2x2x3fobj_copie)
  1078.  
  1079.     best2x2x3fobj_copie = best2x2x3fobj
  1080.     best_temp(:,1) = best2x2x3loc
  1081.     best_temp(:,2) = best2x2x3fobj
  1082.     best_temp = classement_population(best_temp, best2x2x3fobj_copie)
  1083.     best2x2x3loc = best_temp(:,1)
  1084.    
  1085.     !si on n'a résolu aucun 2x2x3, ou un en plus de 20 moves on doit recommencer !!
  1086.     if(best_temp(1,2) < -20) then
  1087.         print*, 'Adding generations to solve the 2x2x3: no good solution was found.'
  1088.         is_continuing = 1
  1089.         GOTO 101
  1090.     end if
  1091.  
  1092.     !sinon, c'est cool, on continue
  1093.     deallocate(pop, perfo, perfo_copie)
  1094.    
  1095.     print*, 'Best 2x2x3 locations : '
  1096.     print*, best2x2x3loc
  1097.     print*, ''
  1098.     print*, 'End of the 2x2x3 search.'
  1099.     print*, 'Alg will now try to go into 2-gen for the best location.'
  1100.     print*, 'Location searched : ', best2x2x3loc(1)
  1101.     print*,''
  1102.  
  1103.  
  1104.     !On réinitialise cube_scrambled avec scramble, puis setup-rotations, puis best 2x2x3 solution
  1105.     loc2x2x3 = best2x2x3loc(1)
  1106.  
  1107.     cube_scrambled = cube_scrambled_copy
  1108.     do ll=1, loc2x2x3/3
  1109.         cube_scrambled = rotate_whole_cube(cube_scrambled)
  1110.         print*, "whole cube clockwise rotation around Oz (= y)"
  1111.         write(10, *), "whole cube clockwise rotation around Oz (= y)"
  1112.     end do
  1113.  
  1114.     select case (modulo(loc2x2x3,3))
  1115.         case(1)
  1116.             cube_scrambled = twist_cube(cube_scrambled)
  1117.             print*, "whole cube rotation around FUR corner (=xy)"
  1118.             write(10, *), "whole cube rotation around FUR corner (=xy)"
  1119.         case(2)
  1120.             do i = 1,2
  1121.                 cube_scrambled = rotate_whole_cube_x(cube_scrambled)
  1122.                 print*, "whole cube rotation around LR horizontal axis (=x)"
  1123.                 write(10, *), "whole cube rotation around LR horizontal axis (=x)"
  1124.             end do
  1125.     end select
  1126.  
  1127.     best_temp(1,:) = fobj(cube_scrambled, cube_solved, best2x2x3elits(1,:), long_code, 3)
  1128.     cube_scrambled = do_sequence(cube_scrambled, best2x2x3elits(1,1:best_temp(1,2)), best_temp(1,2))
  1129.     moves_total = best_temp(1,2)  !comptage pour le nombre de moves de la solution finale
  1130.  
  1131.     !Print dans le fichier de résultats
  1132.     allocate(sol1(3*moves_total))
  1133.     call ToString(best2x2x3elits(1,1:best_temp(1,2)), sol1)
  1134.  
  1135.     !!!!!!!!Algo génétique pour la phase 'getting into 2-gen'
  1136.     taille_pop = 51     !# individus
  1137.     nbre_intrus = 5     !#individus aléatoires remplacent les plus mauvais de pop à chaque gén.
  1138.     long_code  = 30     !nombre de gènes  
  1139.     Ttot = 10000        !nombre de générations
  1140.     pm = 0.05           !proba mutation
  1141.     pc = 0.8            !proba croisement
  1142.     phi = 1.5           !poids élite
  1143.     allocate(pop(taille_pop, long_code))
  1144.     allocate(perfo(taille_pop, 2))
  1145.     allocate(perfo_copie(taille_pop,2))
  1146.  
  1147.     if(is2gen(cube_scrambled)) Ttot = 10
  1148.    
  1149.     !génération population initiale
  1150.     do i = 1, taille_pop
  1151.         do j = 1, long_code
  1152.             call random(r)
  1153.             pop(i,j) = r*0.9999*18
  1154.         end do
  1155.     end do
  1156.    
  1157.  
  1158. 201 do generation = 1, Ttot
  1159.    
  1160.     if(two_gen) pop = mod(pop,2) + 6*(pop/6)        !2-gen-> séquence contient uniquement (F,U)
  1161.     !Raccourci des mouvements qui s'annulent
  1162.     do i = 1, taille_pop
  1163.         pop(i,:) = trim_sequence(pop(i,:))
  1164.     end do
  1165.    
  1166.     !Evaluation de la fonction objectif sur la population
  1167.     !pour fobj : 3=2x2x3, 4=is2gen, 2=entropy
  1168.     do i = 1, taille_pop
  1169.     perfo(i, :) = fobj(cube_scrambled, cube_solved, pop(i, :), long_code, 4)
  1170.     !print*, pop(i,:), perfo(i, 1)
  1171.     end do
  1172.    
  1173.     !classement de la population
  1174.     perfo_copie = perfo
  1175.     pop = classement_population(pop, perfo_copie(:,1))
  1176.     perfo_copie = perfo
  1177.     perfo = classement_population(perfo, perfo_copie(:,1))  !subtil :)
  1178.  
  1179.     !Print de l'état actuel
  1180.     if (modulo(generation, 5000) == 0) then
  1181.     print*, "Generation / elite/ moy. ", generation, perfo(1,:), float(sum(perfo(:,1))/taille_pop)
  1182.     end if
  1183.  
  1184.     !génocide des nmbre_intrus plus mauvais de la pop et remplacement par des aléatoires
  1185.     if(nbre_intrus > 0) then
  1186.         do i = taille_pop-nbre_intrus+1, taille_pop
  1187.             do j = 1, long_code
  1188.                 call random(r)
  1189.                 pop(i,j) = r*0.9999*18
  1190.             end do
  1191.         end do
  1192.     end if
  1193.  
  1194.     !Mariages
  1195.     pop = pop_mariee (pop, phi, pc, perfo)
  1196.  
  1197.     !mutations
  1198.     pop = pop_mutee (pop, pm)
  1199.  
  1200.  
  1201.     end do  !fin boucle sur les generations
  1202.  
  1203.    
  1204.     !Etait-on déjà dans le 2-gen groupe ?
  1205.     if(perfo(1,2)==1 .and. is2gen(cube_scrambled)==1) print*, 'Cube was already in the 2-gen group.'
  1206.     !A-t-on vraiment fini cette étape ?
  1207.  
  1208.     if( sum(perfo(1,:)) == 1700) then
  1209.        
  1210.         print*, 'Getting into 2-gen phase is done :)'
  1211.  
  1212.         allocate(sequence_notation(3*perfo(1,2)))
  1213.         call ToString(pop(1,1:perfo(1,2)), sequence_notation)
  1214.  
  1215.         !Mise à jour de l'état de cube_scrambled si on n'y était pas déjà
  1216.         if(perfo(1,2) > 1) then
  1217.             cube_scrambled = do_sequence(cube_scrambled, pop(1,1:perfo(1,2)), perfo(1,2))
  1218.             moves_total = moves_total + perfo(1,2) !comptage pour #moves solution finale
  1219.             print*, "optimal :"
  1220.             print*, sequence_notation
  1221.             print*, "# moves"
  1222.             print*, perfo(1,2)
  1223.         end if 
  1224.     else
  1225.         print*, 'Adding 10''000 gen. to solve this part'
  1226.         GOTO 201
  1227.     end if
  1228.  
  1229.     print*,''
  1230.  
  1231.     !Prépare le print final dans le fichier
  1232.     allocate(sol2(size(sequence_notation)))
  1233.     sol2 = sequence_notation
  1234.     deallocate(pop, perfo, perfo_copie, sequence_notation)
  1235.  
  1236. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Solving 2-gen !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1237.  
  1238. if(twogen_bourrin > 0) then
  1239.     print*, "calling bourrin"
  1240.     call solve_twogen_bourrin(cube_scrambled, cube_solved)
  1241.     GOTO 9999
  1242. end if
  1243.  
  1244. 300 taille_pop = 51     !# individus
  1245.     nbre_intrus = 5     !#individus aléatoires remplacent les plus mauvais de pop à chaque gén.
  1246.     long_code  = 30     !nombre de gènes  
  1247.     Ttot = 200000       !nombre de générations
  1248.     pm = 0.05           !proba mutation
  1249.     pc = 0.8            !proba croisement
  1250.     phi = 1.5           !poids élite
  1251.     allocate(pop(taille_pop, long_code))
  1252.     allocate(perfo(taille_pop, 2))
  1253.     allocate(perfo_copie(taille_pop,2))
  1254.  
  1255.     two_gen = 1
  1256.  
  1257.     !génération population initiale
  1258.     do i = 1, taille_pop
  1259.         do j = 1, long_code
  1260.             call random(r)
  1261.             pop(i,j) = r*0.9999*18
  1262.         end do
  1263.     end do
  1264.    
  1265.  
  1266. 301 do generation = 1, Ttot
  1267.    
  1268.     if(two_gen) pop = mod(pop,2) + 6*(pop/6)        !2-gen-> séquence contient uniquement (F,U)
  1269.     !Raccourci des mouvements qui s'annulent
  1270.     do i = 1, taille_pop
  1271.         pop(i,:) = trim_sequence(pop(i,:))
  1272.     end do
  1273.    
  1274.     !Evaluation de la fonction objectif sur la population
  1275.     !pour fobj : 3=2x2x3, 4=is2gen, 2=entropy
  1276.     do i = 1, taille_pop
  1277.     perfo(i, :) = fobj(cube_scrambled, cube_solved, pop(i, :), long_code, 2)
  1278.     !print*, pop(i,:), perfo(i, 1)
  1279.     end do
  1280.    
  1281.     !classement de la population
  1282.     perfo_copie = perfo
  1283.     pop = classement_population(pop, perfo_copie(:,1))
  1284.     perfo_copie = perfo
  1285.     perfo = classement_population(perfo, perfo_copie(:,1))  !subtil :)
  1286.  
  1287.     !Print de l'état actuel
  1288.     if (modulo(generation, 10000) == 0) then
  1289.     print*, "Generation / elite/ moy. ", generation, perfo(1,:), float(sum(perfo(:,1))/taille_pop)
  1290.     end if
  1291.  
  1292.     !génocide des nmbre_intrus plus mauvais de la pop et remplacement par des aléatoires
  1293.     if(nbre_intrus > 0) then
  1294.         do i = taille_pop-nbre_intrus+1, taille_pop
  1295.             do j = 1, long_code
  1296.                 call random(r)
  1297.                 pop(i,j) = r*0.9999*18
  1298.             end do
  1299.         end do
  1300.     end if
  1301.  
  1302.     !Mariages
  1303.     pop = pop_mariee (pop, phi, pc, perfo)
  1304.  
  1305.     !mutations
  1306.     pop = pop_mutee (pop, pm)
  1307.  
  1308.  
  1309.     end do  !fin boucle sur les generations
  1310.  
  1311.    
  1312.  
  1313.     !Si on a fini, on a fini, sinon on continue ... quel poète ce cyril !
  1314.  
  1315.     if( (perfo(1,1)+perfo(1,2))/10. == 48) then
  1316.         print*, "optimal :"
  1317.         allocate(sequence_notation(3*perfo(1,2)))
  1318.         call ToString(pop(1,1:perfo(1,2)), sequence_notation)
  1319.         print*, sequence_notation
  1320.        
  1321.         print*, "fobj / # moves / entropy"
  1322.         print*, perfo(1,:), sum(perfo(1,:))/10
  1323.         moves_total = moves_total + perfo(1,2)
  1324.        
  1325.         print*, 'Whole cube was solved in ', moves_total, ' moves :)'
  1326.     else
  1327.         print*, 'Adding 200 000 more generations to solve this stage.'
  1328.         GOTO 301
  1329.     end if
  1330.     print*,''
  1331.  
  1332.     !Prépare le print dans le fichier de résultat
  1333.     allocate(sol3(size(sequence_notation)))
  1334.     sol3 = sequence_notation
  1335.     deallocate(pop, perfo, perfo_copie, sequence_notation)
  1336.  
  1337.  
  1338.  
  1339.  
  1340.  
  1341.     !Print des résultats
  1342. 999 write(10, *) 'Solution : '
  1343.     write(10, *), sol1
  1344.     write(10, *), sol2
  1345.     write(10, *), sol3
  1346.     write(10, *), 'total moves # : ', moves_total
  1347.     close(unit=10)
  1348.  
  1349.     Deallocate(scramble_sequence, scramble_notation, sol1, sol2, sol3)
  1350.    
  1351. 9999    print*, 'End of the program.'
  1352.         read*,i
  1353.     end program RUBIK
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement