/// <summary> /// Remplace chaque occurence d'une variable aléatoirement choisi par une constante, tel que la règle final correspond à un ou plusieurs états de l'environnement. /// Echoue si une variable ne peut être remplacé en constante ou que la règle ne correspond à un ou plusieurs états. /// </summary> /// <param name="index">Index dans l'ensemble d'action.</param> /// <param name="actionSet">Ensemble d'action à traiter.</param> /// <param name="env">Environnement à prendre en compte.</param> /// <returns>Le classifieur fils muté, null si la mutation échoue.</returns> private Classifier VarToConst(int index, List <Classifier> actionSet, PerceivedEnvironnement env) { AppDomainSetup ads = new AppDomainSetup(); ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; AppDomain appDomain = AppDomain.CreateDomain("PrologScript", null, ads); string assembly = Assembly.GetEntryAssembly().FullName; MatchMarshalRefByType mmrbt = (MatchMarshalRefByType)appDomain.CreateInstanceAndUnwrap(assembly, typeof(MatchMarshalRefByType).FullName); List <HornClause> knowBase = fo.knowledgeBase.ToList(); var assertResult = mmrbt.AssertEnvironnement(env, knowBase, boundVarList, fo); Dictionary <string, int> usedPredicate = assertResult.Value.Value; Dictionary <Classifier, List <Attribute> > usedClassifiers = new Dictionary <Classifier, List <Attribute> >(); Dictionary <Attribute, List <HornClause> > accMatchSet = new Dictionary <Attribute, List <HornClause> >(); List <Classifier> matchSetCount = new List <Classifier>(); bool isMatching = false; List <Classifier> actSet = ObjectCopier.Clone(actionSet); Random rand = new Random(); Dictionary <ArgType, Dictionary <string, List <int[]> > > varList = GetAllValues(ArgMode.VAR, actionSet, index); if (varList.Count != 0) { ArgType randArgType = varList.Keys.ToArray()[rand.Next(varList.Keys.Count)];; string randVar = varList[randArgType].Keys.ToArray()[rand.Next(varList[randArgType].Count)]; if (varList[randArgType][randVar].Count != 0) { Attribute newHead = actSet[index].rule.head; Attribute[] newBody = actSet[index].rule.body; if (randArgType is ArgType.TOKEN) { foreach (string constVar in env.tokenOnBoard) { foreach (int[] argIndex in varList[randArgType][randVar]) { if (argIndex[0] == -1) { if (newHead.predOp.argsOptions[argIndex[1]].argsMode.Contains(ArgMode.CONST)) { newHead.values[argIndex[1]] = constVar; } } else { if (newBody[argIndex[0]].predOp.argsOptions[argIndex[1]].argsMode.Contains(ArgMode.CONST)) { newBody[argIndex[0]].values[argIndex[1]] = constVar; } } } Classifier newCl = new Classifier(currentTime, new HornClause(ObjectCopier.Clone(newHead), ObjectCopier.Clone(newBody)), fo); string[] accValues = newHead.values.ToArray() as string[]; List <Attribute> actionMatchList = mmrbt.GetClassifierMatchList(newCl, env); if (actionMatchList.Count != 0) { matchSetCount.Add(newCl); } } } else { foreach (string constVar in boundVarList[randArgType].Keys) { foreach (int[] argIndex in varList[randArgType][randVar]) { if (argIndex[0] == -1) { if (newHead.predOp.argsOptions[argIndex[1]].argsMode.Contains(ArgMode.CONST)) { newHead.values[argIndex[1]] = constVar; } } else { if (newBody[argIndex[0]].predOp.argsOptions[argIndex[1]].argsMode.Contains(ArgMode.CONST)) { newBody[argIndex[0]].values[argIndex[1]] = constVar; } } } Classifier newCl = new Classifier(currentTime, new HornClause(ObjectCopier.Clone(newHead), ObjectCopier.Clone(newBody)), fo); string[] accValues = newHead.values.ToArray() as string[]; List <Attribute> actionMatchList = mmrbt.GetClassifierMatchList(newCl, env); if (actionMatchList.Count != 0) { matchSetCount.Add(newCl); } } } mmrbt.AbolishEnvironnement(usedPredicate); AppDomain.Unload(appDomain); if (matchSetCount.Count != 0) { return(matchSetCount[rand.Next(matchSetCount.Count)]); } } } return(null); }
/// <summary> /// Ajoute un prédicat au corps de la règle et lui octroie des arguments aléatoires entres constantes, variables libres ou liées. /// Si une constante est à ajouter, la règle finale doit correspondre à un ou plusieurs états de l'environnement. /// </summary> /// <param name="index">Index dans l'ensemble d'action.</param> /// <param name="actionSet">Ensemble d'action à traiter.</param> /// <param name="env">Environnement à prendre en compte.</param> /// <returns>Le classifieur fils muté, null si la mutation échoue.</returns> private Classifier AddAtom(int index, List <Classifier> actionSet, PerceivedEnvironnement env) { bool retry = false; Attribute newHead = ObjectCopier.Clone(actionSet)[index].rule.head; Attribute[] newBody = ObjectCopier.Clone(actionSet)[index].rule.body; Classifier newCl = null; List <string> availablePredicates = new List <string>(); foreach (Attribute state in env.states) { if (!availablePredicates.Contains(state.name)) { availablePredicates.Add(state.name); } } Random rand = new Random(); string randAtomName = availablePredicates[rand.Next(availablePredicates.Count)]; string[] randValues = new string[fo.statePredicateOptions[randAtomName].argsOptions.Count()]; Dictionary <int, List <string> > constList = new Dictionary <int, List <string> >(); int atomCount = 0; foreach (Attribute predicate in actionSet[index].rule.body) { if (predicate.name.Equals(randAtomName)) { atomCount++; } } if (atomCount <= fo.statePredicateOptions[randAtomName].max && actionSet[index].rule.body.Length < fo.maxPredicate) { for (int i = 0; i < randValues.Count(); i++) { int accRand; do { retry = false; switch (fo.statePredicateOptions[randAtomName].argsOptions[i].argsMode[accRand = rand.Next(fo.statePredicateOptions[randAtomName].argsOptions[i].argsMode.Count())]) { case ArgMode.CONST: if (fo.statePredicateOptions[randAtomName].argsOptions[i].argType is ArgType.TOKEN) { if (!constList.ContainsKey(i)) { constList.Add(i, env.tokenOnBoard); } } else { if (!constList.ContainsKey(i)) { constList.Add(i, boundVarList[fo.statePredicateOptions[randAtomName].argsOptions[i].argType].Keys.ToList()); } } break; case ArgMode.VAR: randValues[i] = fo.statePredicateOptions[randAtomName].argsOptions[i].argType.ToString() + varCount[fo.statePredicateOptions[randAtomName].argsOptions[i].argType]; varCount[fo.statePredicateOptions[randAtomName].argsOptions[i].argType]++; break; case ArgMode.BOUND: Dictionary <ArgType, Dictionary <string, List <int[]> > > boundList = GetAllValues(ArgMode.BOUND, actionSet, index); if (!boundList.ContainsKey(fo.statePredicateOptions[randAtomName].argsOptions[i].argType) || boundList[fo.statePredicateOptions[randAtomName].argsOptions[i].argType].Count == 0) { return(null); } string randBound = new List <string>(boundList[fo.statePredicateOptions[randAtomName].argsOptions[i].argType].Keys)[rand.Next(boundList[fo.statePredicateOptions[randAtomName].argsOptions[i].argType].Keys.Count)]; randValues[i] = randBound; break; default: retry = true; break; } } while (retry); } if (constList.Count != 0) { AppDomainSetup ads = new AppDomainSetup(); ads.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory; AppDomain appDomain = AppDomain.CreateDomain("PrologScript", null, ads); string assembly = Assembly.GetEntryAssembly().FullName; MatchMarshalRefByType mmrbt = (MatchMarshalRefByType)appDomain.CreateInstanceAndUnwrap(assembly, typeof(MatchMarshalRefByType).FullName); List <HornClause> knowBase = fo.knowledgeBase.ToList(); var assertResult = mmrbt.AssertEnvironnement(env, knowBase, boundVarList, fo); Dictionary <string, int> usedPredicate = assertResult.Value.Value; Dictionary <Classifier, List <Attribute> > usedClassifiers = new Dictionary <Classifier, List <Attribute> >(); Dictionary <Attribute, List <HornClause> > accMatchSet = new Dictionary <Attribute, List <HornClause> >(); List <Classifier> matchSetCount = new List <Classifier>(); List <Attribute> accMatchList = new List <Attribute>(); Dictionary <int, int> accIterators = new Dictionary <int, int>(); foreach (int i in constList.Keys) { accIterators.Add(i, 0); } bool endIterators = false; int accIndex = fo.statePredicateOptions[randAtomName].argsOptions.Count(); while (!endIterators) { newHead = ObjectCopier.Clone(actionSet)[index].rule.head; newBody = ObjectCopier.Clone(actionSet)[index].rule.body; foreach (int i in constList.Keys) { randValues[i] = constList[i][accIterators[i]]; } var acc = ObjectCopier.Clone(newBody).ToList(); acc.Add(new Attribute(randAtomName, randValues.ToArray(), fo.statePredicateOptions[randAtomName])); newBody = acc.ToArray(); newCl = new Classifier(currentTime, new HornClause(newHead, newBody.ToArray()), fo); if ((accMatchList = mmrbt.GetClassifierMatchList(newCl, env)).Count != 0) { matchSetCount.Add(newCl); } for (int i = 0; i <= constList.Last().Key; i++) { if (constList.Keys.Contains(i)) { accIterators[i]++; while (i <= constList.Last().Key&& (!constList.Keys.Contains(i) || accIterators[i] >= constList[i].Count)) { if (constList.Keys.Contains(i)) { accIterators[i] = 0; } i++; } if (accIterators.Values.Sum() == 0 || accIterators[i] < constList[i].Count()) { if (accIterators.Values.Sum() == 0) { endIterators = true; } break; } } } } mmrbt.AbolishEnvironnement(usedPredicate); AppDomain.Unload(appDomain); if (matchSetCount.Count == 0) { return(null); } else { return(matchSetCount[rand.Next(matchSetCount.Count)]); } } List <Attribute> predicateList = new List <Attribute>(actionSet[index].rule.body.ToArray()); predicateList.Add(new Attribute(randAtomName, randValues, fo.statePredicateOptions[randAtomName])); Attribute[] newRule = predicateList.ToArray(); return(new Classifier(currentTime, new HornClause(actionSet[index].rule.head, newRule), fo)); } return(null); }
/// <summary> /// Crée de nouveaux classifieurs dérivant de ceux présents dans l'ensemble d'action en appliquant des opérations de mutations. /// Insère les nouveaux classifieurs dans la population et en supprime si la population est dépassée en terme de capacité. /// Ne se lance que si le temps moyen écoulé depuis le dernier lancement de l'algorithme génétique sur l'ensemble des classifieurs de l'ensemble d'action est plus grand qu'une limite <see cref="FOXCSOptions.geneticThresh"/>. /// </summary> /// <param name="actionSet">Ensemble d'action à traiter.</param> /// <param name="env">Environnement à utiliser.</param> private void RunGeneticAlgorithm(List <Classifier> actionSet, PerceivedEnvironnement env) { int timeNumSum = 0; int numSum = 0; foreach (Classifier cl in actionSet) { timeNumSum += cl.timeStamp * cl.numerosity; numSum += cl.numerosity; } if (numSum == 0) { return; } if (currentTime - timeNumSum / numSum > fo.geneticThresh) { Console.WriteLine("Executing Genetic Algorithm."); Classifier newClassifier = null; Random rand = new Random(); double prob = -1; for (int i = 0; i < actionSet.Count; i++) { actionSet[i].timeStamp = currentTime; while (newClassifier == null) { prob = rand.NextDouble(); if (fo.probMutationRange.mutRanges[0].InRange(prob)) { newClassifier = DeleteAtom(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[1].InRange(prob)) { newClassifier = ConstToVar(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[2].InRange(prob)) { newClassifier = VarToAnonym(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[3].InRange(prob)) { newClassifier = AddAtom(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[4].InRange(prob)) { newClassifier = VarToConst(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[5].InRange(prob)) { newClassifier = AnonymToVar(i, actionSet, env); } else if (fo.probMutationRange.mutRanges[6].InRange(prob)) { newClassifier = Reproduction(i, actionSet, env); } if (newClassifier != null) { int popIndex = ActionSetIndexOf(actionSet, newClassifier); if (popIndex != -1) { actionSet[popIndex].numerosity++; } else { popIndex = PopSetIndexOf(newClassifier); if (popIndex != -1) { popSet[popIndex].numerosity++; } else { popSet.Add(newClassifier); } } DeleteFromPopulation(); } } } } }
private void DeleteFromPopulation() { int popSize = 0; double fitnessSum = 0; foreach (Classifier cl in popSet) { popSize += cl.numerosity; fitnessSum += cl.fitness; } while (popSize > fo.popMaxSize) { double averageFitnessInPop = fitnessSum / popSize; double voteSum = 0; foreach (Classifier cl in popSet) { voteSum += DeletionVote(cl, averageFitnessInPop); } double choicePoint = new Random().NextDouble() * voteSum; voteSum = 0; for (int i = 0; i < popSet.Count; i++) { voteSum += DeletionVote(popSet[i], averageFitnessInPop); if (voteSum > choicePoint) { if (popSet[i].numerosity > 1) { popSet[i].numerosity--; } else { Classifier accCl = popSet[i]; popSet.RemoveAt(i); if (matchSet.Count != 0) { foreach (KeyValuePair <Attribute, List <Classifier> > matchSubSet in ObjectCopier.Clone(matchSet)) { if (matchSubSet.Value.Contains(accCl)) { matchSubSet.Value.RemoveAll(cl => cl.rule == accCl.rule); if (matchSubSet.Value.Count == 0) { matchSet.Remove(matchSubSet.Key); } } } } } break; } popSize = 0; fitnessSum = 0; foreach (Classifier cl in popSet) { popSize += cl.numerosity; fitnessSum += cl.fitness; } } } }
public YPMatchThread(ref Classifier cl, Attribute action) { this.cl = cl; this.action = action; this.clMatchList = new List <Attribute>(); }
/// <summary> /// Méthode gérant la concordance d'un classifieur /// </summary> /// <param name="cl">Classifieur à vérifier.</param> /// <param name="env">Environnement à insérer dans la base de prédicats.</param> /// <param name="knowledgeBase">Clause constiuant la base de connaissance.</param> /// <returns></returns> public List <Attribute> GetClassifierMatchList(Classifier cl, PerceivedEnvironnement env) { List <Attribute> clMatchList = new List <Attribute>(); Dictionary <string, int> usedPredicate = new Dictionary <string, int>(); List <YPMatchThread> ypts = new List <YPMatchThread>(); List <Task> threads = new List <Task>(); foreach (Attribute action in env.actions) { if (cl.rule.head.name.Equals(action.name)) { if (cl.rule.clause == null) { lock (_lock) cl.rule.YPwriteAndCompile(); } ypts.Insert(0, new YPMatchThread(ref cl, action)); threads.Insert(0, new Task(ypts[0].ActionMatch)); threads[0].Start(); } /* * * * if (cl.rule.head.name.Equals(action.name)) * { * if (cl.rule.clause == null) * lock (_lock) * cl.rule.YPwriteAndCompile(); * foreach (bool l1 in cl.rule.Match(action.values)) * { * clMatchList.Add(action); * break; * } * } * */ } for (int j = 0; j < threads.Count; j++) { try { threads[j].Wait(); threads[j].Dispose(); } catch (Exception e) { Console.WriteLine("Erreur provenant de YieldProlog, relancement du thread YPThread."); Console.ReadKey(); Console.WriteLine(e); threads[j].Dispose(); threads.Insert(0, new Task(ypts[j].ActionMatch)); } } foreach (YPMatchThread ypt in ypts) { foreach (Attribute actionMatch in ypt.clMatchList) { if (!clMatchList.Contains(actionMatch)) { clMatchList.Add(actionMatch); } } } return(clMatchList); }