static QGraph SmartMutateQGraph(QGraph graph) { QGraph mutant = new QGraph(ref graph); mutant.edgeMutationChance += mutant.mutationIncrement * (0.5f - UnityEngine.Random.value); mutant.actionMutationChance += mutant.mutationIncrement * (0.5f - UnityEngine.Random.value); mutant.addNodeChance += mutant.mutationIncrement * (0.5f - UnityEngine.Random.value); mutant.changeInterruptWeightChance += mutant.mutationIncrement * (0.5f - UnityEngine.Random.value); // float mutationIncrement = 0.001f; // // float edgeMutationChance = 0.1f; // float actionMutationChance = 0.1f; // float addNodeChance = 0.8f; // float changeInterruptWeightChance = 0.01f; //mutate edges List <QGraphNode> t_nodes = new List <QGraphNode> (mutant.nodes); float n_c = t_nodes.Count; float numChanges = n_c; t_nodes = Utils.ShuffleList <QGraphNode> (t_nodes); float max_delta_reward = 0; float min_delta_reward = 0; //calculate max and min change in reward between two nodes for (int i = 0; i < n_c; ++i) { for (int j = 0; j < mutant.nodes [i].outgoingEdges.Count; ++j) { float delta = (mutant.nodes [mutant.nodes [i].outgoingEdges [j].targetNode].Reward - mutant.nodes [i].Reward); if (max_delta_reward < delta) { max_delta_reward = delta; } if (min_delta_reward > delta) { min_delta_reward = delta; } } } for (int i = 0; i < numChanges; ++i) { for (int j = 0; j < mutant.nodes [i].outgoingEdges.Count; ++j) { float mutationChance = (mutant.nodes [mutant.nodes [i].outgoingEdges [j].targetNode].Reward - mutant.nodes [i].Reward) / (max_delta_reward - min_delta_reward); if (UnityEngine.Random.value > mutationChance * 0.8f) { mutant.nodes [i].outgoingEdges [j] = QGraphEdge.MutateEdge(mutant.nodes [i].outgoingEdges [j], mutant.possibleStates, mutant.mutationIncrement, mutant.stateConstraints); } } } //mutate nodes //numChanges = mutant.nodes.Count * mutant.actionMutationChance; t_nodes = Utils.ShuffleList <QGraphNode> (t_nodes); for (int i = 0; i < numChanges; ++i) { int nodeToChange = UnityEngine.Random.Range(0, t_nodes.Count); t_nodes [nodeToChange] = QGraphNode.MutateNode(t_nodes [nodeToChange], mutant.possibleActions, mutant.actionConstraints); } //add nodes numChanges = mutant.nodes.Count * mutant.addNodeChance; t_nodes = Utils.ShuffleList <QGraphNode> (t_nodes); if (numChanges < 1) { numChanges = 1f; } for (int i = 0; i < numChanges; ++i) { QGraphNode newNode = new QGraphNode(t_nodes [UnityEngine.Random.Range(0, t_nodes.Count - 1)]); newNode = QGraphNode.MutateNode(newNode, mutant.possibleActions, mutant.actionConstraints); int numNodesToConnectTo = (int)(n_c * mutant.numNodesToConnectToNewNode); if (numNodesToConnectTo < 1) { numNodesToConnectTo = 1; } List <QGraphNode> nodesToRandomlyConnectToTemp = new List <QGraphNode> (mutant.nodes); nodesToRandomlyConnectToTemp = Utils.ShuffleList(nodesToRandomlyConnectToTemp); //connect nodes to the new node for (int j = 0; j < numNodesToConnectTo; ++j) { QGraphEdge temp_edge = new QGraphEdge(mutant.nodes.Count); if (mutant.possibleStates.Count > 0) { temp_edge.RequiredStates = new List <string> { mutant.possibleStates [j % mutant.possibleStates.Count] }; } temp_edge.Float_restrictions = new List <float> (mutant.float_restriction_range.Count); for (int k = 0; k < temp_edge.Float_restrictions.Count; ++k) { temp_edge.Float_restrictions.Add(UnityEngine.Random.Range(mutant.float_restriction_range [k].min, mutant.float_restriction_range [k].max)); } temp_edge.Float_mult = new List <float> (mutant.float_mult); temp_edge.Comparison_operators = new List <ComparisonOperator> (mutant.comparison_operators); nodesToRandomlyConnectToTemp [j].AddEdge(temp_edge); } numNodesToConnectTo = (int)(n_c * mutant.numNodesToConnectNewNodeTo); if (numNodesToConnectTo < 1) { numNodesToConnectTo = 1; } //connect the new node to other nodes; nodesToRandomlyConnectToTemp = Utils.ShuffleList(nodesToRandomlyConnectToTemp); for (int j = 0; j < numNodesToConnectTo; ++j) { QGraphEdge temp_edge = new QGraphEdge(mutant.nodes.IndexOf(nodesToRandomlyConnectToTemp [j])); if (mutant.possibleStates.Count > 0) { temp_edge.RequiredStates = new List <string> { mutant.possibleStates [j % mutant.possibleStates.Count] }; } temp_edge.Float_restrictions = new List <float> (mutant.float_restriction_range.Count); for (int k = 0; k < temp_edge.Float_restrictions.Count; ++k) { temp_edge.Float_restrictions.Add(UnityEngine.Random.Range(mutant.float_restriction_range [k].min, mutant.float_restriction_range [k].max)); } temp_edge.Float_mult = new List <float> (mutant.float_mult); temp_edge.Comparison_operators = new List <ComparisonOperator> (mutant.comparison_operators); newNode.AddEdge(temp_edge); } mutant.nodes.Add(newNode); } mutant.ResetCurrentNodeToRoot(); mutant.memoryWindow = new List <QGraphNode> (graph.memoryWindow.Count); mutant.windowSize = graph.windowSize; mutant.windowIndex = 0; mutant.memoryWindow.Add(mutant.currentNode); return(mutant); }