private void _PrintPath(CirclePathTreeNodeModel treeRoot) { this._logger.LogInformation($""); this._logger.LogInformation($"----------START Circle path tree."); var pathList = this._GetPathesAsStringList(new List <CirclePathTreeNodeModel>() { treeRoot }); foreach (var pathItem in pathList) { this._logger.LogInformation(pathItem); } this._logger.LogInformation($"----------END Circle path tree."); this._logger.LogInformation($""); }
/// <summary> /// Traverses the pathes tree and returns a list of pathes. /// </summary> /// <param name="pathFindResultTreeNode"></param> /// <returns></returns> private List <List <string> > _BuildPathListFromTree(CirclePathTreeNodeModel pathFindResultTreeNode) { // recursion safety stop condition 0 if (pathFindResultTreeNode == null) { return(null); } //var result = new List<List<string>>(); // recursion stop condition 1 if (pathFindResultTreeNode.IsLeafNode) { return(new List <List <string> >() { new List <string>() { pathFindResultTreeNode.State } }); } else { // recursive call var nextResults = pathFindResultTreeNode.NextNodes .Select(nextNode => this._BuildPathListFromTree(nextNode)) .SelectMany(nextResult => nextResult) // flatten .Select(nextResult => { // prepend with current state nextResult.Insert(0, pathFindResultTreeNode.State); return(nextResult); }) .ToList(); return(nextResults); } }
/// <summary> /// Recursive. /// <br/> /// Finds a set of pathes which describes a valid transition from start state back to itself /// according to min/max path length limitations. /// <br/> /// Result: A tree that represents valid pathes. /// </summary> /// <param name="absoluteStartState">Static param, doesn't change accross recursive calls.</param> /// <param name="relativeStartStates">Dynamic param that changes accross recursive calls.</param> /// <param name="pathLength">Dynamic param that changes accross recursive calls.</param> /// <returns></returns> private List <CirclePathTreeNodeModel> _FindPathTree(string absoluteStartState, List <string> relativeStartStates, int pathLength = -1) { pathLength += 1; List <CirclePathTreeNodeModel> result = relativeStartStates.Select(state => { if (pathLength >= 1 && pathLength < this._minPathLenght) { if (state == absoluteStartState) { // while we haven't reached the min length forbid absolute start state to apear in path return(null); } } else if (pathLength >= this._minPathLenght && pathLength < this._maxPathLength) { if (state == absoluteStartState) { // min length circle path reached // this._logger.LogInformation($"Found min length circle path: {absoluteStartState} -> {state}. len={pathLength}."); return(new CirclePathTreeNodeModel() { State = state, NextNodes = null, PathLength = pathLength, }); } } else if (pathLength == this._maxPathLength) { // max path length reached if (state == absoluteStartState) { // ended in absolute start state - desired result // this._logger.LogInformation($"Max level reached: {absoluteStartState} -> ... -> {state}. len={pathLength}."); return(new CirclePathTreeNodeModel() { State = state, NextNodes = null, PathLength = pathLength, }); } else { // ended in other state than start - discard this path return(null); } } else if (pathLength > this._maxPathLength) { // out of path length limits - discard this path return(null); } var stateTransitions = this._FindStateTransitions(state); var nextStates = this._GetSutableTransitionStatesForState(stateTransitions, state); // recursive call // traverse down to the tree var nextResults = this._FindPathTree(absoluteStartState, nextStates, pathLength); if (nextResults != null) { var result = new CirclePathTreeNodeModel() { State = state, NextNodes = nextResults, PathLength = pathLength, }; return(result); } return(null); }).ToList(); // filter out discarded pathes result = result.Where(x => x != null).ToList(); if (result.Count() == 0) { return(null); } return(result); }