public double Analyze(List <GeneValue> cromosomeDeobfiscated) { /* * семантическое значение последовательности генов: * последовательность узлов по которому может идти пакет * * семантическое значение счета: * общая длина предлагаемой последовательности узлов, ведь чем она меньше - тем более оптимальный получается путь (?) */ GeneValue previous = null; double ret = 0; foreach (var item in cromosomeDeobfiscated) { //GD.Print((item as NodeValue).GetValue()); if (previous != null) { ret += netContainer.GetValue((previous as NodeValue).GetValue(), (item as NodeValue).GetValue()); } previous = item; } return(ret); }
private void SetGeneImage(AlienGeneValue geneValue) { //leave empty if negative if (geneValue.Value < 0 || geneValue.Value >= geneValue.GeneData.Values.Count) { return; } GeneValue geneDataValue = geneValue.GeneData.Values[geneValue.Value]; geneValue.GeneSlot.Image.sprite = geneDataValue.Image; geneValue.GeneSlot.ImageOutLine.sprite = geneDataValue.Outline; }
public GeneValue Mutate(GeneValue toMutate) { // полный отрыв при проведении мутации return(possibleOutcomes[rnd.Next(possibleOutcomes.Length - 1)]); }
/// <summary> /// History로부터 읽어온 데이터를 바탕으로, 유전 선택 알고리즘을 수행합니다. 우성 : 열성이 3:1 비율이 되도록 집단에서 우성 행동들과 열성 행동의 3차원 배열값을 반환합니다. /// </summary> /// <param name="ObjectCollection">3차원으로 구성된 Selection 대상 ObjectCollection 입니다.</param> /// <param name="ActionMap">Selection 대상 ActionMap 입니다.</param> /// <param name="SimonFunctions">Selection 연산에 사용될 SimonFunction 집합입니다.</param> /// <returns>선택된 3차원 ActionDNA 배열입니다.</returns> public List<List<List<SIMONGene>>> Selection(SIMONCollection ObjectCollection, SIMONCollection ActionMap, Dictionary<string, SIMONFunction> SimonFunctions) { List<List<List<SIMONGene>>> selectedDNA = new List<List<List<SIMONGene>>>(); List<GeneValue[]> recordMap = new List<GeneValue[]>(); //ObjectCollection 내 각 객체들에 대한 Action들에 대한 Record 값들을 저장하는 Map. int ObjectCount = ObjectCollection.Count; int ActionCount = ActionMap.Count; for (int i = 0; i < ActionCount; i++) { selectedDNA.Add(new List<List<SIMONGene>>()); } #region 현재 ActionMap 구조를 이용한 RecordMap 구조화 for (int i = 0; i < ActionCount; i++) { List<SIMONObject> elementList = (List<SIMONObject>)ActionMap.ValueOfIndex(i); int actionObjectCount = elementList.Count; GeneValue[] gene = new GeneValue[actionObjectCount]; recordMap.Add(gene); for (int j = 0; j < actionObjectCount; j++) { recordMap[i][j] = new GeneValue(); SIMONObject[] otherObjectsList; if (ObjectCount > 1) otherObjectsList = new SIMONObject[ObjectCollection.Count - 1]; else otherObjectsList = null; int otherObjectCnt = 0; for (int k = 0; k < ObjectCount; k++) if ((otherObjectsList != null) && (!ObjectCollection.ValueOfIndex(k).Equals(elementList[j]))) otherObjectsList[otherObjectCnt++] = (SIMONObject)ObjectCollection.ValueOfIndex(k); for (int k = 0; k < elementList[j].Actions.Count; k++) { if (elementList[j].Actions[k].ActionName.Equals(ActionMap.KeyOfIndex(i))) { recordMap[i][j].dna = elementList[j].Actions[k].ActionDNA; double fitnessValue = (double)SimonFunctions[elementList[j].Actions[k].FitnessFunctionName].Invoke(elementList[j], otherObjectsList); //Upper Boundary와 Lower Boundary 내의 Fitness Value들을 채택. if (fitnessValue < SIMONConstants.FITNESS_MIN_VALUE) { throw new SIMONFramework.ValueUnderflowException(SIMONConstants.EXP_VALUE_UNDERFLOW); } else if (fitnessValue > SIMONConstants.FITNESS_MAX_VALUE) { throw new SIMONFramework.ValueOverflowException(SIMONConstants.EXP_VALUE_OVERFLOW); } recordMap[i][j].fitnessValue = fitnessValue; break; } } } } #endregion #region 현재 division 나누는 코드. Action 별로 4등분해서 나누기 때문에 2차원 배열임. int[][] divIndex = new int[ActionCount][]; for (int i = 0; i < ActionCount; i++) { int numberOfActionObjects = ((List<SIMONObject>)ActionMap.ValueOfIndex(i)).Count; divIndex[i] = new int[SIMONConstants.GENE_SUM_RATING]; for (int j = 0; j < SIMONConstants.GENE_SUM_RATING; j++) { int divPosition = (numberOfActionObjects * (j + 1)) / SIMONConstants.GENE_SUM_RATING; if (divPosition == 0) divPosition = -1; else divPosition--; divIndex[i][j] = divPosition; } } #endregion //QuickSort를 통해서 각 Action별로 fitness 값들을 정렬. for (int i = 0; i < recordMap.Count; i++) QuickSort(recordMap[i], 0, recordMap[i].Length - 1); List<List<GeneValue>> firstSelectGene = new List<List<GeneValue>>(); List<List<GeneValue>> lastSelectGene = new List<List<GeneValue>>(); for (int i = 0; i < recordMap.Count; i++) { firstSelectGene.Add(new List<GeneValue>()); lastSelectGene.Add(new List<GeneValue>()); List<GeneValue> recessiveGroup = new List<GeneValue>(); List<GeneValue> dominionGroup = new List<GeneValue>(); //열성집합 중 1만큼의 비율을 선택. 경계값부터 시작인덱스 까지 내려가면서 집합에 포함시킨다. for (int j = divIndex[i][(SIMONConstants.GENE_RECESSIVE_RATING - 1)]; j >= 0; j--) { recessiveGroup.Add(recordMap[i][j]); } List<GeneValue> rouletteRecessive = RouletteWheel(recessiveGroup, GeneSelectionLaw.RECESSIVE); //각 Object 들의 열성 집합 중 대표값 배열을 우성 열성 비율별로 선택 if (rouletteRecessive != null) firstSelectGene[i].AddRange(rouletteRecessive); //우성집합 중 3만큼의 비율을 선택. 경계값부터 시작인덱스까지 내려가면서 집합에 포함시킨다. for (int j = divIndex[i][SIMONConstants.GENE_DOMINION_RATING]; j >= divIndex[i][(SIMONConstants.GENE_RECESSIVE_RATING - 1)] + 1; j--) { dominionGroup.Add(recordMap[i][j]); } List<GeneValue> rouletteDominion = RouletteWheel(dominionGroup, GeneSelectionLaw.DOMINION); //각 Object 들의 우성 집합 중 대표값 배열을 우성 열성 비율별로 선택 if (rouletteDominion != null) firstSelectGene[i].AddRange(rouletteDominion); lastSelectGene[i].AddRange(RouletteWheel(firstSelectGene[i], GeneSelectionLaw.DOMINION)); } for (int i = 0; i < ActionCount; i++) { int selectedCount = SIMONConstants.GENE_REAL_SELECT_NUM; int[] selectedIdxList = new int[lastSelectGene[i].Count]; int selectedIdxListIndex = 0; //만약 실제 유전자 숫자가 Default로 정한 유전자 추출 갯수보다 작으면 실제 유전자 갯수 만큼을 선택 횟수로 지정한다. if (lastSelectGene[i].Count < SIMONConstants.GENE_REAL_SELECT_NUM) selectedCount = lastSelectGene[i].Count; if (selectedCount <= 0) continue; //실제 유전시킬 유전자 갯수만큼 랜덤값을 통한 추출 while (selectedIdxListIndex < selectedCount) { Random rand = new Random(); int selectIdx = rand.Next(0, selectedCount); bool retryFlag = false; for (int j = 0; j < selectedIdxListIndex; j++) { if (selectIdx == selectedIdxList[j]) { retryFlag = true; break; } } if (retryFlag) continue; selectedDNA[i].Add(lastSelectGene[i][selectIdx].dna); selectedIdxList[selectedIdxListIndex++] = selectIdx; } } //selectedDNA 리턴. return selectedDNA; }
/// <summary> /// History로부터 읽어온 데이터를 바탕으로, 유전 선택 알고리즘을 수행합니다. 우성 : 열성이 3:1 비율이 되도록 집단에서 우성 행동들과 열성 행동의 2차원 배열값을 반환합니다. /// </summary> /// <param name="PropertyCollection">2차원으로 구성된 Selection 대상 ObjectCollection 입니다.</param> /// <param name="SimonFunctions">Selection 연산에 사용될 SimonFunction 집합입니다.</param> /// <returns>선택된 2차원 Property DNA 배열입니다.</returns> public List<List<SIMONGene>> Selection(SIMONCollection PropertyCollection, Dictionary<string, SIMONFunction> SimonFunctions) { List<List<SIMONGene>> selectedDNA = new List<List<SIMONGene>>(); int dnaObjectCount = PropertyCollection.Count; GeneValue[] propertyGenes = new GeneValue[dnaObjectCount]; int[] divIndex = new int[SIMONConstants.GENE_SUM_RATING]; for (int i = 0; i < dnaObjectCount; i++) { SIMONObject elementObject = (SIMONObject)PropertyCollection.ValueOfIndex(i); SIMONObject[] otherObjects = new SIMONObject[dnaObjectCount - 1]; int otherObjectsCnt = 0; propertyGenes[i] = new GeneValue(); //otherObject 리스트 추가시키면됨. for (int j = 0; j < dnaObjectCount; j++) if (elementObject != (SIMONObject)PropertyCollection.ValueOfIndex(j)) otherObjects[otherObjectsCnt++] = (SIMONObject)PropertyCollection.ValueOfIndex(j); propertyGenes[i].dna = elementObject.PropertyDNA; double fitnessValue = (double)SimonFunctions[elementObject.ObjectFitnessFunctionName].Invoke(elementObject, otherObjects); //Upper Boundary와 Lower Boundary 경계 내의 Fitness Value를 채택. if (fitnessValue < SIMONConstants.FITNESS_MIN_VALUE) { throw new SIMONFramework.ValueUnderflowException(SIMONConstants.EXP_VALUE_UNDERFLOW); } else if (fitnessValue > SIMONConstants.FITNESS_MAX_VALUE) { throw new SIMONFramework.ValueOverflowException(SIMONConstants.EXP_VALUE_OVERFLOW); } propertyGenes[i].fitnessValue = fitnessValue; } QuickSort(propertyGenes, 0, dnaObjectCount - 1); for (int i = 0; i < SIMONConstants.GENE_SUM_RATING; i++) { int divNum = (int)(((i + 1) * dnaObjectCount) / SIMONConstants.GENE_SUM_RATING); if (divNum == 0) divNum = -1; else divNum--; divIndex[i] = divNum; } List<GeneValue> recessiveGroup = new List<GeneValue>(); List<GeneValue> dominionGroup = new List<GeneValue>(); List<GeneValue> selectedGene = new List<GeneValue>(); for (int i = divIndex[SIMONConstants.GENE_RECESSIVE_RATING - 1]; i >= 0; i--) { recessiveGroup.Add(propertyGenes[i]); } selectedGene.AddRange(RouletteWheel(recessiveGroup, GeneSelectionLaw.RECESSIVE)); for (int i = divIndex[SIMONConstants.GENE_DOMINION_RATING]; i >= divIndex[SIMONConstants.GENE_RECESSIVE_RATING - 1] + 1; i--) { dominionGroup.Add(propertyGenes[i]); } selectedGene.AddRange(RouletteWheel(dominionGroup, GeneSelectionLaw.DOMINION)); int selectingCount = SIMONConstants.GENE_REAL_SELECT_NUM; if (selectedGene.Count < selectingCount) selectingCount = selectedGene.Count; int[] selectedIdxTable = new int[selectingCount]; int selectedIdx = 0; if (selectedGene.Count <= 0) return selectedDNA; while (selectedIdx < selectingCount) { Random rand = new Random(); int selectIdx = rand.Next(0, selectedGene.Count); bool retryFlag = false; for (int i = 0; i < selectedIdx; i++) { if (selectedIdxTable[i] == selectIdx) { retryFlag = true; break; } } if (retryFlag) continue; selectedDNA.Add(selectedGene[selectIdx].dna); selectedIdxTable[selectedIdx++] = selectIdx; } return selectedDNA; }
private void QuickSort(GeneValue[] dnaList, int left, int right) { int index = left, jndex = right; double pivot = dnaList[(left + right) / 2].fitnessValue; while (index <= jndex) { while (dnaList[index].fitnessValue < pivot) index++; while (dnaList[jndex].fitnessValue > pivot) jndex--; if (index <= jndex) { GeneValue temp = dnaList[index]; dnaList[index] = dnaList[jndex]; dnaList[jndex] = temp; index++; jndex--; } } if (left < jndex) QuickSort(dnaList, left, jndex); if (right > index) QuickSort(dnaList, index, right); }