


BeginPackage["GenetickyAlgoritmus`"]

Inicializace::usage="Inicializace[x] .. kde x je pocet jedincu"
OptimalizacniSmycka::usage="proste spust OptimalizacniSmycka[pocet iteraci] a uvidis!"

Begin["Private`"];

(***************************************************
 * Konverze                                        *
 ***************************************************)

Clear[CisloNaRetezec];
CisloNaRetezec[cislo_, delka_] :=
Module[{temp, retezec},
       (*       If[cislo >= 1 || cislo < 0, Throw[{"CisloNaRetezec::vyjimka:", cislo, " je mimo rozsah"}],]; *)
       temp = RealDigits[cislo, 2];
       retezec = Take[ Join[ Table[0, {-temp[[2]]}] , temp[[1]] , Table[0, {delka}]], delka ];
       If[Global`pouzitGrayCode, BinaryToGray[retezec], retezec]
];

Clear[RetezecNaCislo];
RetezecNaCislo[retezec_]:=
Module[{i, temp},
       temp=If[Global`pouzitGrayCode, GrayToBinary[retezec], retezec];
       N[Sum[temp[[i]]*2^(-i), {i, Length[temp]}]]
];

Clear[VektorNaRetezec];
VektorNaRetezec[vek_] :=
Module[{i, x1, x2, pocetBitu},
       If[(Length[vek] - 1) != Length[Global`VektorPromennych], Throw["VektorNaRetezec::nesedi delka vektoru promenych"]];
       Flatten[
            Table[
                  x1 = Global`VektorPromennych[[i, 2]];
                  x2 = Global`VektorPromennych[[i, 3]];
                  cislo = (vek[[i]] - x1)/(x2 - x1);
                  CisloNaRetezec[cislo, Global`VektorPromennych[[i, 4]]]
                  , {i, 1, Length[Global`VektorPromennych]}
            ]
       ]
];


Clear[RetezecNaVektor];
RetezecNaVektor[ret_] :=
Module[{temp, docasny, num, x1, x2, retval},
       docasny = ret;
       retval = Table[
                   temp = Take[docasny, Global`VektorPromennych[[i, 4]]];
                   docasny = Drop[docasny, Global`VektorPromennych[[i, 4]]];
                   num = RetezecNaCislo[temp];
                   x1 = Global`VektorPromennych[[i, 2]];
                   x2 = Global`VektorPromennych[[i, 3]];
                   num*(x2 - x1) + x1
                   , {i, 1, Length[Global`VektorPromennych]}];
       Join[retval, {Global`Fitness[retval]}]
];



BinaryToGray[retezec_] :=
Module[{index},
       Join[
        {First[retezec]},
        Reverse[
                Table[If[retezec[[index - 1]] == 1, 1 - retezec[[index]],
                         retezec[[index]]], {index, Length[retezec], 2, -1}]]
       ]
]

GrayToBinary[retezec_] :=
Module[{index, spravne = True},
       Table[
          If[(spravne && retezec[[index]] == 1) ||  (! spravne &&
                                                     retezec[[index]] == 0),
             spravne = False; 1,
             spravne = True; 0
          ]
          , {index, 1, Length[retezec]}]
];



(***************************************************
 * Selekce                                         *
 ***************************************************)


Clear[VyberElity];
VyberElity[gen_, pocet_] := Module[{temp, elita},
                                (*           temp = Sort[Union[gen], Last[#1] <= Last[#2] &];*)
                                (*
                                 If[Length[temp] < pocet,
                                    Throw["Vyjimka ve vyberu elity - homogenni generace"],];*)
                                (*
                                 elita = Take[temp, pocet];*)
                                (*   elita *)
    {NajdiMinimum[gen]}
]


Clear[KorelacePoctu];
KorelacePoctu[gen_] := Module[{temp},
             If[Length[gen] > Global`pocetJedincu,
                Delete[gen, NajdiIndexMaxima[gen]], gen]
]



Clear[Recombination];
Recombination[ parents_ ] := Module[{},
  If [Parents[parents]<2, Throw["Recombination::error"]];
  Module[{},
    If[OddQ[Random[Integer, {1, 10}]],
      GeneticOperators`NPointCrossover[{parents[[1]], parents[[2]]}, 1],
      GeneticOperators`UniformCrossover[parents]]
      ]];

Clear[RandomPositionsSelection];
RandomPositionsSelection[ number_, range_ ] := Module[{PositionArray, RangeArray},
  If[number>range, Throw["RandomPositionsSelection::Vybirate vice indexu nez muzete"]];
  RangeArray=Range[range];
  PositionArray=Sort[Table[
      Module[{index, value},
        index=Random[Integer, {1, Length[RangeArray]}];
        value=RangeArray[[index]];
        RangeArray=Delete[RangeArray, index];
        value],
   {number}]];
   PositionArray
];

Clear[SplitString];
SplitString[string_, cutpoints_] := Module[{SplittedArray},
  SplittedArray=Table[
      Take[string, {cutpoints[[i]]+1, cutpoints[[i+1]]}]
  , {i, 1, Length[cutpoints]-1}];

  If[Last[cutpoints]<Length[string], AppendTo[SplittedArray, Take[string, {Last[cutpoints]+1, Length[string]}]]];
  PrependTo[SplittedArray, Take[string,{1,cutpoints[[1]]}]];

  SplittedArray
];



(***************************************************
 * Generacni Operace                               *
 ***************************************************)

Clear[UdelejKrizeni];
UdelejKrizeni[pop_] := Module[{r1, r2, retezec, cislo1, cislo2, pop1},
    r1 = Random[Integer, {1, Length[pop]}];
While[(r2 = Random[Integer, {1, Length[pop]}]) == r1,Null];
     retezec = If[ Random[] < Global`pravdepodobnostKrizeni,
      Recombination[{VektorNaRetezec[pop[[r1]]], VektorNaRetezec[pop[[r2]]]}],
      {VektorNaRetezec[pop[[r1]]], VektorNaRetezec[pop[[r2]]]}];
cislo1 = RetezecNaVektor[retezec[[1]]];
cislo2 = RetezecNaVektor[retezec[[2]]];
pop1 = Delete[pop, {{r1}, {r2}}];
{pop1, {cislo1, cislo2}}
];

Clear[UdelejKrizeniVsech];
UdelejKrizeniVsech[pop_] := Module[{pracpop, temp, novapop = {}},
    pracpop = pop;
Table[
    temp = UdelejKrizeni[pracpop];
pracpop = temp[[1]];
AppendTo[novapop, temp[[2, 1]]];
AppendTo[novapop, temp[[2, 2]]];
, {IntegerPart[Length[pop]/2]}
];
novapop
];

Clear[UdelejMutaci];
UdelejMutaci[pop_] := Module[{index},
  Table[RetezecNaVektor[GeneticOperators`Mutation[VektorNaRetezec[pop[[index]]]]],{index, 1, Length[pop]}]
  ];

(***************************************************
* Ruzne
***************************************************)

Clear[VygenerujJedince];
VygenerujJedince := Module[{x1, x2},
    Table[
x1 = Global`VektorPromennych[[i, 2]];
x2 = Global`VektorPromennych[[i, 3]];
Random[Real, {x1, x2}]
, {i, 1, Length[Global`VektorPromennych]}]
    ]

Clear[Inicializace];
Inicializace[pocet_] := Module[{temp},
                    Table[temp = VygenerujJedince;
    Flatten[{temp, Global`Fitness[temp]}], {pocet}]];

Clear[NajdiIndexMinima];
NajdiIndexMinima[vek_] := Position[Map[Last[#] &, vek], Min[Map[Last[#] &, vek]]][[1, 1]]

Clear[NajdiMinimum];
NajdiMinimum[vek_] := Part[vek, Position[Map[Last[#] &, vek], Min[Map[Last[#] &, vek]]][[1, 1]]]

NajdiMinimum[vek_] := Module[{minimum, j},
  minimum = vek[[1]];
For[ j = 1, j <= Length[vek], j++,
            If[Last[minimum] > Last[vek[[j]]], minimum = vek[[j]];];];
minimum
]

Clear[NajdiIndexMaxima];
NajdiIndexMaxima[vek_] :=
Position[Map[Last[#] &, vek], Max[Map[Last[#] &, vek]]][[1, 1]]


Clear[NajdiMaximum];
NajdiMaximum[vek_] :=
Part[vek, Position[Map[Last[#] &, vek], Max[Map[Last[#] &, vek]]][[1, 1]]]

NajdiMaximum[vek_] := Module[{maximum = vek[[1]], j},
  For[ j = 1, j <= Length[vek], j++,
              If[Last[maximum] < Last[vek[[j]]], maximum = vek[[j]];];];
maximum
  ]

Clear[OptimalizacniSmycka];
OptimalizacniSmycka[pocetIteraci_]:=
Print[Catch[Timing[Table[
elita = VyberElity[Global`Populace, 1];
Global`Populace = If[Global`pouzitRuletu,
  GeneticOperators`RouletteWheelSelection[Global`Populace],
  GeneticOperators`TurnajovaSelekce[Global`Populace]];
Global`Populace = Join[Global`Populace, elita];
Global`Populace = UdelejKrizeniVsech[Global`Populace];
Global`Populace = KorelacePoctu[Global`Populace];
Global`Populace = UdelejMutaci[Global`Populace];
Global`Populace = Join[Global`Populace, elita];
Print[N[VyberElity[Global`Populace, 1], 10]];
Global`Populace = KorelacePoctu[Global`Populace];
, {pocetIteraci}]]]];


End[ ]
EndPackage[ ]

