#***** Inicializacio *****


#** Objektumok torlese **


rm(list=ls())


#** Parameterek beallitasa **

#* Kielegitheto halozat
#Logikai_Halozat <- c('or',2,3,'and',4,5,'and',5,9,'and',6,7,'and',8,9,'and',10,11,'not',11,0,'and',12,13,'or',14,15)

Logikai_Halozat <- c('or',2,3,'and',4,5,'and',6,10,'or',8,9,'not',7,0,'not',11,0,'or',8,10)

#* Kielegithetetlen halozat
#Logikai_Halozat <- c('and',2,3,'and',4,5,'and',5,9,'and',6,7,'and',8,9,'and',10,11,'not',11,0,'and',12,13,'or',14,15)
Populacio_Szamossaga <- 5
Generacio_Maximum <- 100
Legjobb_Egyed_Mutacios_Valoszinusege <- .7
Mutacio_Ciklus_Szama <- 5
Bitszintu_Mutacio_Valoszinusege <- .7
Josag_Szint <- .5


#** Deklaracio es Ertekadas **

i <- numeric
j <- numeric
k <- numeric
Generacio_Index <- numeric

Halozat_Hossza <- length(Logikai_Halozat)

Logikai_Kapuk_Szama <- Halozat_Hossza / 3
Logikai_Kapuk <- character(length = Logikai_Kapuk_Szama)
	i <- 1
	j <- 1
	while (i <= Halozat_Hossza)
	{
		Logikai_Kapuk[j] <- Logikai_Halozat[i]
		i <- i + 3
		j <- j + 1
	}

Kapcsolodas_Lista <- numeric(length = 2 * Logikai_Kapuk_Szama)
	i <- 1
	j <- 1
	while (i <= Halozat_Hossza)
	{
		Kapcsolodas_Lista[j] <- as.numeric(Logikai_Halozat[i + 1])
		Kapcsolodas_Lista[j + 1] <- as.numeric(Logikai_Halozat[i + 2])
		i <- i + 3
		j <- j + 2
	}

Kapcsolodas_Tomb <- array(Kapcsolodas_Lista, dim = c(2, Logikai_Kapuk_Szama))

Egyed_Hossza <- max(Kapcsolodas_Tomb)

Populacio_Josaga <- array(0, dim = Populacio_Szamossaga)
Populacio_SegedTomb <- matrix(data = c(1, rep.int(2, Egyed_Hossza - 1)), nrow = Populacio_Szamossaga, ncol = Egyed_Hossza, byrow = TRUE)
Populacio_SegedTomb_Alap <- matrix
POPULACIO_SEGEDTOMB <- matrix
Populacio <- matrix(nrow = Populacio_Szamossaga, ncol = Egyed_Hossza)
POPULACIO <- matrix
Egyed <- array(dim = Egyed_Hossza)
Osszes_Legjobb_Egyed <- matrix(nrow = Generacio_Maximum, ncol = Egyed_Hossza)
Uj_Populacio <- matrix(nrow = Populacio_Szamossaga, ncol = Egyed_Hossza)

Populacio_SegedTomb_Alap <- Populacio_SegedTomb

Populacio_Josag_Index <- array

Alak <- NULL
	i <- 1
	while (i <= Logikai_Kapuk_Szama)
	{
		Alak <- c(Alak, i)
		Alak <- c(Alak, c(Kapcsolodas_Tomb[1, i], Kapcsolodas_Tomb[2, i]))
		i <- i + 1
	}
Alak <- rev(Alak)
SzintTomb_Seged <- array(0, dim = c(2, Halozat_Hossza))
SzintLista_Seged <- array(0, dim = c(1, Halozat_Hossza))
Szintek <- numeric(length = Logikai_Kapuk_Szama)
	Szint <- function(i, szint_seged, h, alak)
	{
		if (i == h) return(szint_seged)
		
		j <- ((i%/%3) + 1) * 3
	
		szint_seged[1, j] <- 1
		szint_seged[2, j] <- i
		
		k <- h
	
		while (alak[k] != alak[j])k <- k - 1
		
		Szint(k, szint_seged, h, alak)
	}

	k <- 1
	while (k <= Halozat_Hossza-1)
	{
		if (!SzintTomb_Seged[1, k])
		{
			b <- ((k%/%3) + 1) * 3
			if (!SzintTomb_Seged[1, b])
			{
				SzintTomb_Seged = Szint(k, SzintTomb_Seged, Halozat_Hossza, Alak)
	
				i<-Halozat_Hossza
				j<-0
				while (i>=1)
				{
					if (SzintTomb_Seged[2, i]) 
					{		
						SzintTomb_Seged[1, i] <- SzintTomb_Seged[1, i] + j
						j <- j + 1
					}
					i <- i - 1
				}
			}
		}
		k <- k + 1
		SzintTomb_Seged[2, ] = 0
	}
	
	SzintLista_Seged <- rev(SzintTomb_Seged[1, ])
	
	i <- 1
	j <- 1
	while (i<=Halozat_Hossza)
	{
		Szintek[j] <- SzintLista_Seged[i]
		i <- i + 3
		j<- j + 1
	}
Szint_Maximum <- max(Szintek)
Egyed_SzintTomb <- numeric(length = Egyed_Hossza)
	i<-1
	while (i<=Egyed_Hossza)
	{
		if (i <= length(Szintek)) Egyed_SzintTomb[i] <- Szintek[i]
		else Egyed_SzintTomb[i] = Szint_Maximum + 1
		i <- i + 1
	}
Szint_Maximum <- max(Egyed_SzintTomb)

Josag_Maximum <- 0
	i<-2
	while (i <= Egyed_Hossza)
	{
		Josag_Maximum <- Josag_Maximum + 2**(Szint_Maximum+1 - Egyed_SzintTomb[i])
		i <- i + 1
	}

Josag_Maximum_Nemzettseg <- array(0, dim = Generacio_Maximum)
Josag_Atlag_Nemzettseg <- array(0, dim = Generacio_Maximum)
Josag_Osszeg <- numeric
Josag_Atlag <- numeric

Summa <- numeric
Van_Megoldas <- FALSE

Nemzettseg_Josag_Index <- array
Nemzettseg_Legjobb_Egyed_Indexe <- numeric

Egyezo_Josag_Maximum <- numeric
Egyezo_Josag_Maximum_Szazalek <- numeric


#** Fuggveny Deklaracio **

Josag_Fuggveny <- function(egyed, popt, kt, lk, lksz)
{
	i <- 1
	#Amíg van kapu.
	while (i <= lksz)
	{
		#Ha az egyed tömb előző eleme elfogadható, az előző ciklusban állítódik be.
		if (popt[i] == 1)	
		{
			#Kapu értékeinek megfelelő kiértékelés.
			switch(lk[i],
				and = 
				{	
					#Ha igaz a kapu, átvesszük az egyed kapuhoz csatlakozó értékeit.
					if (egyed[i])
					{
						if (popt[kt[1, i]]) popt[kt[1, i]] <- egyed[kt[1, i]]
						if (popt[kt[2, i]]) popt[kt[2, i]] <- egyed[kt[2, i]]
					}
					#Ha hamis a kapu értéke, akkor csak a dupla igaz csatlakozó értéket nem fogadjuk el.
					#Egyébként minden más jó lesz a következő kiértékeléshez.
					else
					{
						if (egyed[kt[1, i]] && egyed[kt[2, i]]) 
						{
							popt[kt[1, i]] <- 0
							popt[kt[2, i]] <- 0
						}
						else
						{
							if (popt[kt[1, i]]) popt[kt[1, i]] <- 1
							if (popt[kt[2, i]]) popt[kt[2, i]] <- 1
						}
					}
				},
				or = 
				{
					#Ha a kapu értéke igaz, mindkét ágat elfogadjuk, ha nem hamis mindkét kapcsolódó ág.
					if (egyed[i])
					{
						if (!(egyed[kt[1, i]] || egyed[kt[2, i]]))
						{
							popt[kt[1, i]] <- 0
							popt[kt[2, i]] <- 0
						}
						else
						{
							if (popt[kt[1, i]]) popt[kt[1, i]] <- 1
						 	if (popt[kt[2, i]]) popt[kt[2, i]] <- 1
						}
					}
					#Hamis érték eseténm mindkét ágnál az ellentétes bit lesz az elfogadható.
					else
					{
						if (egyed[kt[1, i]]) popt[kt[1, i]] <- 0
						else if (popt[kt[1, i]]) popt[kt[1, i]] <- 1
						if (egyed[kt[2, i]]) popt[kt[2, i]] <- 0
						else if (popt[kt[2, i]]) popt[kt[2, i]] <- 1
					}
				},
				not = 
				{
					#Ha a kapcsolódó kapu ellentétes bit-ű, akkor elfogadjuk.
					if (egyed[i] == !egyed[kt[1, i]])
					{
						if (popt[kt[1, i]]) popt[kt[1, i]] <- 1
					}
					else popt[kt[1, i]] <- 0
				}
			)
		}
		i <- i + 1
	}

	#A segédtömb kihasználatlan bitjeinek nullázása a kiértékeléshez.
	popt[popt == 2] <- 0

	return(popt)
}


Rajzol <- function(xmax, ymax, red, green)
{
	one2xmax <- seq(from = 1, to = xmax)

	plot.new()
	plot.window(c(0,xmax),c(0,ymax))
	title(main = "A genetikus algoritmus futása", sub = "Alsó felirat")
	axis(1)
	axis(2)
	box()
	legend("bottomright", c("Maximális jóság", "Átlagos jósag"),col=2:3, pch = 1, title = "bottomright")
	points(one2xmax, red, col = "RED")
	points(one2xmax, green, col = "GREEN")
}


#***** Program *****


#** Populacio Inicializalasa **
	
i <- 1
while (i <= Populacio_Szamossaga)
{
	Egyed <- c(1, sample(c(0, 1), replace = TRUE, size = Egyed_Hossza - 1))
	Populacio[i,] <- as.matrix(Egyed)
	i <- i + 1
}

#** Generacios ciklus **

Generacio_Index <- 1
repeat
{

#** Populacio kiertekelese **

	i <- 1
	Josag_Osszeg <- 0
	while (i <= Populacio_Szamossaga)
	{
		Populacio_SegedTomb[i, ] <- Josag_Fuggveny(Populacio[i, ], Populacio_SegedTomb[i, ], Kapcsolodas_Tomb, Logikai_Kapuk, Logikai_Kapuk_Szama)
	

		j <- 2
		Josag_Seged <- 0
		
		while (j <= Egyed_Hossza)
		{
			if (Populacio_SegedTomb[i,j]) Josag_Seged <- Josag_Seged + 2 ** (Szint_Maximum + 1 - Egyed_SzintTomb[j])
			j <- j + 1
		}
		Populacio_Josaga[i] <- Josag_Seged
		Josag_Osszeg <- Josag_Osszeg + Populacio_Josaga[i]
		i <- i + 1
	}
	Josag_Atlag <- Josag_Osszeg / Populacio_Szamossaga

	Josag_Maximum_Nemzettseg[Generacio_Index] <- max(Populacio_Josaga)
	Josag_Atlag_Nemzettseg[Generacio_Index] <- Josag_Atlag

#** Kivalasztas **

	Populacio_Josag_Index <- sort(Populacio_Josaga,decreasing = TRUE, index.return = TRUE)
	Legjobb_Egyed_Indexe <- Populacio_Josag_Index$ix[1]

	Osszes_Legjobb_Egyed[Generacio_Index, ] <- Populacio[Legjobb_Egyed_Indexe, ]

#** Keresztezes **

	j <- 2
	while (j <= Populacio_Szamossaga)
	{
		i <- 1
		while (i <= Egyed_Hossza)
		{
			Veletlen_Szam <- runif(1)	
			if (Populacio_SegedTomb[Legjobb_Egyed_Indexe, i]) 
			{
				if (Populacio_SegedTomb[Populacio_Josag_Index$ix[j], i])
				{
					Uj_Populacio[j, i] <- Populacio[Populacio_Josag_Index$ix[j], i]
				}
				else 
				{
					Uj_Populacio[j, i] <- Populacio[Legjobb_Egyed_Indexe, i]
				}
			}
			else 
			{	
				if (Populacio_SegedTomb[Populacio_Josag_Index$ix[j], i])	
					Uj_Populacio[j, i] <- Populacio[Populacio_Josag_Index$ix[j], i]
				else
				{
					if (Veletlen_Szam > .5)
					{
						Uj_Populacio[j, i] <- Populacio[Legjobb_Egyed_Indexe, i]
					}
					else 
					{
						Uj_Populacio[j, i] <- Populacio[Populacio_Josag_Index$ix[j], i]
					}
				}
			}
			i <- i + 1
		}
		j <- j + 1
	}

	Uj_Populacio[1,1] <- 1
	i<-2
	while (i <= Egyed_Hossza)
	{
		Veletlen_Szam <- runif(1)
		if (Veletlen_Szam > Legjobb_Egyed_Mutacios_Valoszinusege)
			if (Populacio[Legjobb_Egyed_Indexe,i])
				Uj_Populacio[1,i] <- 0
			else
				Uj_Populacio[1,i] <- 1
		else
			Uj_Populacio[1,i] <- Populacio[Legjobb_Egyed_Indexe,i]
		i <- i + 1
	}

#** Felteteles mutacio **

	if (Generacio_Index > Mutacio_Ciklus_Szama)
	{
		Summa <- 0
		for (i in 1:Mutacio_Ciklus_Szama) Summa <- Summa + Josag_Maximum_Nemzettseg[(Generacio_Index - Mutacio_Ciklus_Szama + i)]
		Summa <- Summa / Mutacio_Ciklus_Szama
		if (Summa == Josag_Maximum_Nemzettseg[Generacio_Index])
		{
			j <- 1
			while (j <= Populacio_Szamossaga)
			{
				Populacio_SegedTomb


				i <- 2
				while (i <= Egyed_Hossza)
				{
					Veletlen_Szam <- runif(1)
					if (Veletlen_Szam > Bitszintu_Mutacio_Valoszinusege)
						if (Uj_Populacio[j,i])
							Uj_Populacio[j,i] <- 0
						else
							Uj_Populacio[j,i] <- 1				
					i <- i + 1
				}
				j <- j + 1
			}
		}
	}

#** Uj populacio letrehozasa **

	Populacio <- Uj_Populacio
	Populacio_SegedTomb <- Populacio_SegedTomb_Alap

#** Kilepesi feltetel vizsgalata **

	if (Josag_Maximum_Nemzettseg[Generacio_Index] == Josag_Maximum)
	{
		print("A program elerte a megoldast: ")
		print(Generacio_Index)
		print("ciklus alatt.")
		print("A megoldast ado bitek: ")
		print(Osszes_Legjobb_Egyed[Generacio_Index, (Logikai_Kapuk_Szama + 1) : Egyed_Hossza])
		Van_Megoldas <- TRUE
		break
	}

	if (Generacio_Index == Generacio_Maximum)
		break

#** Uj generacios ciklus **

	Generacio_Index <- Generacio_Index + 1
}

Nemzettseg_Josag_Index <- sort(Populacio_Josaga,decreasing = TRUE, index.return = TRUE)
Nemzettseg_Legjobb_Egyed_Indexe <- Nemzettseg_Josag_Index$ix[1]

Egyezo_Josag_Maximum <- length(Josag_Maximum_Nemzettseg[Josag_Maximum_Nemzettseg == max(Josag_Maximum_Nemzettseg)])
Egyezo_Josag_Maximum_Szazalek <- Egyezo_Josag_Maximum / Generacio_Maximum

if (!Van_Megoldas)
{
	print("A elertem a maximalis futashosszt es nem talaltam eredmenyt!")
	if (Egyezo_Josag_Maximum_Szazalek > Josag_Szint)
	{
		print("Velemenyem szerint a halozat logikai ellentmondas.")
	}
	else
	{
		print("Velemenyem szerint a halozat kielegitheto, ")
		print("a legjobb egyed bemeneti bitjei: ")
		print(Osszes_Legjobb_Egyed[Nemzettseg_Legjobb_Egyed_Indexe, (Logikai_Kapuk_Szama + 1) : Egyed_Hossza])
	}
}


#** Függvény kirajzolása **

Rajzol(Generacio_Index, Josag_Maximum, Josag_Maximum_Nemzettseg[1:Generacio_Index], Josag_Atlag_Nemzettseg[1:Generacio_Index])


