6

编辑 3:好的,所以我的代码可以工作,但是如果我使用 16 个节点和 11 以上的搜索深度,我将面临巨大的内存消耗问题。

一个 soemone 检查代码并告诉我如何纠正该内存泄漏?

这是完整的代码:

public void searchTSP(
    int depth,
    RouterPoint startpoint,
    bool isRound,
    IRouter<RouterPoint> router)
{
  #region TSP_startpointCheck
  if (!routepoints[0].Location.Equals(startpoint.Location))
  {
    int index = Array
      .FindIndex(routepoints, x => x.Location == startpoint.Location);

    if (index != -1 && index != 0) //it's somewhere in the array
    {
      RouterPoint temprp = routepoints[0];
      routepoints[0] = routepoints[index]; //put it to index 0
      routepoints[index] = temprp;
    }
    else //it's not in the array
    {
      //we add it...
      RouterPoint[] ta = new RouterPoint[routepoints.Length + 1];
      routepoints.CopyTo(ta, 0);
      ta[routepoints.Length] = startpoint;
      ta.CopyTo(routepoints, 0);
    }
  }
  #endregion

  selectedRouter = router;
  if (pathDictionary == null)
  {
    pathDictionary = new Dictionary<int[], double>(new IntArrayComparer());
    fillDictionary();
  }            

  DecisionPath bestPath = new DecisionPath();
  //DecisionPath currentPath = new DecisionPath();
  //List<DecisionPath> listOfPaths = new List<DecisionPath>();
  //List<int> visited = new List<int>();
  //List<RouterPoint> waypoints = routepoints.ToList();

  DateTime start = DateTime.Now;
  RouteNode root = new RouteNode();
  root.parent = null;
  root.curr = 0;
  root.weight = 0.0f;
  root.isTerminal = false;
  root.memory = new List<short>();
  root.memory.Add(root.curr);
  calculateChildren(root);

  double bestval=double.MaxValue;
  while (bestPath.list.Count < routepoints.GetLength(0))
  {
    bestval = double.MaxValue;
    int bestIndex = 0;
    for (int i = 0; i < root.children.Count; i++)
    {
      RouteNode child = root.children[i];
      double t = minimax(child, depth);
      if (t < bestval)
      {
        bestval = t;
        bestIndex = i;
        bestPath.cost = bestval;
        bestPath.list = child.memory;
      }
    }

    RouteNode temp = root.children[bestIndex];
    root.children.Clear();
    root.children.Add(temp);
    root = root.children[0];
  }

  //My result is in the bestPath class 
  // which has two properties: a list of indexes
  // representing my found result node sequence
  // and a double containing the total cost of the path
}

class RouteNode
{
  public RouteNode parent { get; set; }
  public short curr { get; set; }
  public bool isTerminal { get; set; }
  public float weight { get; set; }
  public List<RouteNode> children { get; set; }
  public List<short> memory { get; set; }
}

/// <summary>
/// List of all children of a node that should be removed
/// </summary>
private List<RouteNode> killList;

/// <summary>
/// MiniMax recursive search for deciding witch ode to go to
/// </summary>
/// <param name="point">Input node</param>
/// <param name="depth">How deep will we search</param>
/// <returns>Weight value</returns>
private double minimax(RouteNode point, int depth)
{
  if (point.isTerminal || depth <= 0)
  {
    //if (point.isTerminal)
    if (point.weight < bestyVal)
    {
      bestyVal = point.weight;
      //Console.WriteLine(
      //    "{0} - {1}",
      //    string.Join(", ", point.memory.ToArray()),
      //    point.weight.ToString());
    }

    return point.weight;
  }

  double alpha = double.PositiveInfinity;
  if (point.children == null || point.children.Count == 0 )
    calculateChildren(point);

  killList = new List<RouteNode>();
  for (int i=0; i< point.children.Count; i++)
  {
    RouteNode child = point.children[i];
    if (child != null)
    {
      if (!child.isTerminal && child.weight > bestyVal)
      {
        child = null;
        continue;
      }

      alpha = Math.Min(alpha, minimax(child, depth - 1));
    }
    else
      continue;
  }

  point.children.RemoveAll( e => killList.Contains(e));
  //killList = null;
    return alpha;
}

/// <summary>
/// Calculates possible children for a node
/// </summary>
/// <param name="node">Input node</param>
private void calculateChildren(RouteNode node)
{
  int c = node.curr;
  List<int> possibleIndexes = Enumerable
      .Range(0, routepoints.GetLength(0))
      .ToList();

  RouteNode curNod = node;

  if (node.children == null)
    node.children = new List<RouteNode>();

  while (curNod != null)
  {
    possibleIndexes.Remove(curNod.curr);
    curNod = curNod.parent;
  }
  //imamo še neobiskane potomce...
  foreach (int i in possibleIndexes)
  {
    RouteNode cc = new RouteNode();
    cc.curr = (short)i;
    cc.parent = node;
    double temp=0.0;
    if (!pathDictionary.TryGetValue(new int[] { node.curr, i }, out temp))
    {
      //preracunajPoti(node.curr, i, selectedRouter);
      throw new Exception(
          String.Format(
              "Missed a path? {0} - {1}",
              node.curr,
              i));
    }

    cc.weight = cc.parent.weight + (float)temp;
    cc.memory = node.memory.ToList();
    cc.memory.Add(cc.curr);

    if (possibleIndexes.Count == 1)
      cc.isTerminal = true;
    else
      cc.isTerminal = false;

    node.children.Add(cc);
  }
  //jih dodamo
  possibleIndexes = null;    
}
4

1 回答 1

1

只需为此投入两分钱,@ mao47 就已经死了,因为没有内存泄漏,只是需要大量内存。

我在寻找有关 MinMax 搜索的文章时遇到了这个线程,值得补充的是,在优化 MinMax 和其他算法方面还有很多工作要做。例如,我发现这篇论文很有用(考虑到我个人的学术衰退率和毕业后的时间 t,语言是可以合理理解的)。

于 2013-09-05T15:12:51.327 回答