Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Tarjan算法-Python到scala_Python_Scala_Translate_Tarjans Algorithm - Fatal编程技术网

Tarjan算法-Python到scala

Tarjan算法-Python到scala,python,scala,translate,tarjans-algorithm,Python,Scala,Translate,Tarjans Algorithm,我正在尝试将递归转换为scala,尤其是这一部分: def tarjan_recursive(g): S = [] S_set = set() index = {} lowlink = {} ret = [] def visit(v): index[v] = len(index) lowlink[v] = index[v]

我正在尝试将递归转换为scala,尤其是这一部分:

def tarjan_recursive(g):
        S = []
        S_set = set()
        index = {}
        lowlink = {}
        ret = []
        def visit(v):
                index[v] = len(index)
                lowlink[v] = index[v]
                S.append(v)
                S_set.add(v)

                for w in g.get(v,()):
                        print(w)
                        if w not in index:
                                visit(w)
                                lowlink[v] = min(lowlink[w], lowlink[v])
                        elif w in S_set:
                                lowlink[v] = min(lowlink[v], index[w])
                if lowlink[v] == index[v]:
                        scc = []
                        w = None
                        while v != w:
                                w = S.pop()
                                scc.append(w)
                                S_set.remove(w)
                        ret.append(scc)

        for v in g:
                print(index)
                if not v in index:
                        visit(v)
        return ret
我知道scala中有tarjan算法或者,但是它没有返回好的结果,请从python中翻译它,帮助我理解它

以下是我所拥有的:

def tj_recursive(g: Map[Int,List[Int]])= {
        var s : mutable.ListBuffer[Int] = new mutable.ListBuffer()
        var s_set : mutable.Set[Int] = mutable.Set()
        var index : mutable.Map[Int,Int] =  mutable.Map()
        var lowlink : mutable.Map[Int,Int]=  mutable.Map()
        var ret : mutable.Map[Int,mutable.ListBuffer[Int]]= mutable.Map()

        def visit(v: Int):Int = {
                 index(v) = index.size
               lowlink(v) = index(v)
               var zz :List[Int]= gg.get(v).toList(0)
                            for( w <- zz) {
                  if( !(index.contains(w)) ){
                     visit(w)
                     lowlink(v) = List(lowlink(w),lowlink(v)).min
                   }else if(s_set.contains(w)){
                     lowlink(v)=List(lowlink(v),index(w)).min
                   }
               }

               if(lowlink(v)==index(v)){
                  var scc:mutable.ListBuffer[Int] = new mutable.ListBuffer()
                  var w:Int=null.asInstanceOf[Int]
                  while(v!=w){
                    w= s.last
                    scc+=w
                    s_set-=w
                  }
           ret+=scc
        }
        }

   for( v <- g) {if( !(index.contains(v)) ){visit(v)}}
   ret
}
在这条线上

if(lowlink(v)==index(v)){ 
我想是从这一行来的,但我不确定:

if( !(index.contains(w)) 
但调试它真的很难,因为我不能直接打印我的错误


谢谢

下面是Python的直译:

def tj_recursive(g: Map[Int, List[Int]])= {
  val s = mutable.Buffer.empty[Int]
  val s_set = mutable.Set.empty[Int]
  val index = mutable.Map.empty[Int, Int]
  val lowlink = mutable.Map.empty[Int, Int]
  val ret = mutable.Buffer.empty[mutable.Buffer[Int]]

  def visit(v: Int): Unit = {
    index(v) = index.size
    lowlink(v) = index(v)
    s += v
    s_set += v

    for (w <- g(v)) {
      if (!index.contains(w)) {
        visit(w)
        lowlink(v) = math.min(lowlink(w), lowlink(v))
      } else if (s_set(w)) {
        lowlink(v) = math.min(lowlink(v), index(w))
      }
    }

    if (lowlink(v) == index(v)) {
      val scc = mutable.Buffer.empty[Int]
      var w = -1

      while(v != w) {
        w = s.remove(s.size - 1)
        scc += w
        s_set -= w
      }

      ret += scc
    }
  }

  for (v <- g.keys) if (!index.contains(v)) visit(v)
  ret
}

实现中最大的问题是
visit
的返回类型(应该是
Unit
,而不是
Int
)以及在最终的
理解中迭代图形的项目而不是图形的键,但为了风格和清晰度,我做了许多其他编辑(同时仍保持基本形状)。

这里是一个迭代版本。它是中算法递归版本的翻译

返回:

ArrayBuffer(ArrayBuffer(1, 3, 2), ArrayBuffer(7, 6), ArrayBuffer(4, 5), ArrayBuffer(8))

我知道这篇文章很老,但我最近一直在从事Scala中Tarjans算法的实现。在代码的实现过程中,我看到了这篇文章,我突然想到,可以用一种更简单的方式来完成:

case class Edge[A](from: A, to: Set[A])

class TarjanGraph[A](src: Iterable[Edge[A]]) {
  lazy val trajan: mutable.Buffer[mutable.Buffer[A]] = {
    var s = mutable.Buffer.empty[A] //Stack to keep track of nodes reachable from current node
    val index = mutable.Map.empty[A, Int] //index of each node
    val lowLink = mutable.Map.empty[A, Int] //The smallest index reachable from the node
    val ret = mutable.Buffer.empty[mutable.Buffer[A]] //Keep track of SCC in graph
def visit(v: A): Unit = {
  //Set index and lowlink of node on first visit
  index(v) = index.size
  lowLink(v) = index(v)
  //Add to stack
  s += v
  if (src.exists(_.from == v)) {
    for (w <- src.find(e => e.from == v).head.to) {
      if (!index.contains(w)) { //Node is not explored yet
        //Perform DFS from node W
        visit(w)
        //Update the lowlink value of v so it has the value of the lowest node reachable from itself and from node w
        lowLink(v) = math.min(lowLink(w), lowLink(v))
      } else if (s.contains(w)) {
        // Node w is on the stack meaning - it means there is a path from w to v
        // and since node w is a neighbor to node v there is also a path from v to w
        lowLink(v) = math.min(lowLink(v), index(w))
      }
    }
  }
  //The lowlink value haven't been updated meaning it is the root of a cycle/SCC
  if (lowLink(v) == index(v)) {
    //Add the elements to the cycle that has been added to the stack and whose lowlink has been updated by node v's lowlink
    //This is the elements on the stack that is placed behind v
    val n = s.length - s.indexOf(v)
    ret += s.takeRight(n)
    //Remove these elements from the stack
    s.dropRightInPlace(n)
  }
}

//Perform a DFS from  all no nodes that hasn't been explored
src.foreach(v => if (!index.contains(v.from)) visit(v.from))
ret
  }

  // A cycle exist if there is a SCC with at least two components
  lazy val hasCycle: Boolean = trajan.exists(_.size >= 2)
  lazy val trajanCycle: Iterable[Seq[A]] = trajan.filter(_.size >= 2).distinct.map(_.toSeq).toSeq
  lazy val topologicalSortedEdges: Seq[Edge[A]] =
    if (hasCycle) Seq[Edge[A]]()
    else trajan.flatten.reverse.flatMap(x => src.find(_.from == x)).toSeq
}
案例类边缘[A](从:A到:设置[A])
类TarjanGraph[A](src:Iterable[Edge[A]]{
lazy val trajan:mutable.Buffer[mutable.Buffer[A]={
var s=mutable.Buffer.empty[A]//堆栈以跟踪可从当前节点访问的节点
val index=mutable.Map.empty[A,Int]//每个节点的索引
val lowLink=mutable.Map.empty[A,Int]//可从节点访问的最小索引
val ret=mutable.Buffer.empty[mutable.Buffer[A]]//在图形中跟踪SCC
def就诊(v:A):单位={
//在第一次访问时设置节点的索引和下限链接
索引(v)=索引大小
低链接(v)=索引(v)
//添加到堆栈
s+=v
如果(src.exists(u.from==v)){
for(we.from==v.head.to){
如果(!index.contains(w)){//节点尚未探索
//从节点W执行DFS
访问(w)
//更新v的lowlink值,使其具有可从自身和节点w访问的最低节点的值
低链接(v)=数学最小值(低链接(w),低链接(v))
}否则,如果(s.包含(w)){
//节点w位于堆栈上,这意味着有一条从w到v的路径
//因为节点w是节点v的邻居,所以也有一条从v到w的路径
低链接(v)=数学最小值(低链接(v),索引(w))
}
}
}
//lowlink值尚未更新,这意味着它是循环/SCC的根
if(低链接(v)=索引(v)){
//将元素添加到已添加到堆栈且其lowlink已由节点v的lowlink更新的循环中
//这是堆栈上放置在v后面的元素
val n=s.length-s.indexOf(v)
ret+=s.takeRight(n)
//从堆栈中删除这些元素
s、 dropRightInPlace(n)
}
}
//从所有未探测的无节点执行DFS
src.foreach(v=>if(!index.contains(v.from))访问(v.from))
ret
}
//如果存在至少含有两个部件的SCC,则存在一个循环
lazy val hasCycle:Boolean=trajan.exists(u.size>=2)
lazy val trajanCycle:Iterable[Seq[A]=trajan.filter(u.size>=2).distinct.map(u.toSeq).toSeq
lazy val TopologicalSortedGes:Seq[Edge[A]]=
if(hasCycle)Seq[Edge[A]]()
else trajan.flatte.reverse.flatMap(x=>src.find(u.from==x)).toSeq
}

嘿,特拉维斯,谢谢你的帮助。我想我已经解决了图形项的问题,但是没有:/I我现在要检查缓冲区。再次感谢你!
case class Arc[A](from:A, to:A)

class SparseDG[A](src: Iterable[Arc[A]]) {

  val verts = (src.map(_.from) ++ src.map(_.to)).toSet.toIndexedSeq
  val qVert = verts.size
  val vertMap = verts.zipWithIndex.toMap
  val indexedSrc = src.map{ arc => Arc(vertMap(arc.from), vertMap(arc.to)) }

  val exit  = (0 until qVert)
              .map(v => indexedSrc.filter(_.from == v).map(_.to).toIndexedSeq)


  lazy val tarjan_iterative: Seq[Seq[A]] = {
    trait Step
    case object SetDepth           extends Step
    case object ConsiderSuccessors extends Step
    case object CalcLowlink        extends Step
    case object PopIfRoot          extends Step
    case class StackFrame(v:Int, next:Step)

    val result = Buffer[Seq[A]]()
    val index = new Array[Int](qVert).map(_ => -1)   // -1 = undefined
    val lowlink = new Array[Int](qVert).map(_ => -1) // -1 = undefined
    val wIndex = new Array[Int](qVert)               // used to iterate w nodes
    var _index = 0
    val s = Stack[Int]()
    val isRemoved = BitSet()
    val strongconnect = Stack[StackFrame]()

    (0 until qVert).foreach { v_idx =>
      if(index(v_idx) == -1) {
        strongconnect.push(StackFrame(v_idx, SetDepth))
        while(!strongconnect.isEmpty) {
          val StackFrame(v, step) = strongconnect.pop()
          step match {
            case SetDepth =>
              index(v) = _index
              lowlink(v) = _index
              _index += 1
              s.push(v)
              isRemoved.remove(v)
              strongconnect.push(StackFrame(v, ConsiderSuccessors))

            case ConsiderSuccessors =>
              if(wIndex(v) < exit(v).size){
                val w = exit(v)(wIndex(v))
                if(index(w) == -1){
                  strongconnect.push(StackFrame(v, CalcLowlink))
                  strongconnect.push(StackFrame(w, SetDepth))
                }
                else{
                  if(!isRemoved.contains(w)){
                    if(lowlink(v) > lowlink(w)) lowlink(v) = index(w)
                  }
                  wIndex(v) += 1
                  strongconnect.push(StackFrame(v, ConsiderSuccessors))
                }
              }
              else{
                strongconnect.push(StackFrame(v, PopIfRoot))
              }

            case CalcLowlink =>
              val w = exit(v)(wIndex(v))
              if(lowlink(v) > lowlink(w)) lowlink(v) = lowlink(w)
              wIndex(v) += 1
              strongconnect.push(StackFrame(v, ConsiderSuccessors))

            case PopIfRoot =>
              if(index(v) == lowlink(v)){
                val buf = Buffer[A]()
                var w = 0
                do{
                  w = s.pop()
                  isRemoved += w
                  buf += verts(w)
                }
                while(w != v)
                result += buf.toSeq
              }
          }
        }
      }
    }
    result.toSeq
  }

  lazy val hasCycle = tarjan_iterative.find(_.size >= 2).isDefined

  lazy val topologicalSort =
    if(hasCycle) None
    else         Some(tarjan_iterative.flatten.reverse)

}
val g = new SparseDG(Seq(
        Arc("1","2"),
        Arc("2","3"),
        Arc("3","1"),
        Arc("4","2"),
        Arc("4","3"),
        Arc("6","3"),
        Arc("6","7"),
        Arc("7","6"),
        Arc("4","5"),
        Arc("5","4"),
        Arc("5","6"),
        Arc("8","5"),
        Arc("8","8"),
        Arc("8","7")
      ))

g.tarjan_iterative
ArrayBuffer(ArrayBuffer(1, 3, 2), ArrayBuffer(7, 6), ArrayBuffer(4, 5), ArrayBuffer(8))
case class Edge[A](from: A, to: Set[A])

class TarjanGraph[A](src: Iterable[Edge[A]]) {
  lazy val trajan: mutable.Buffer[mutable.Buffer[A]] = {
    var s = mutable.Buffer.empty[A] //Stack to keep track of nodes reachable from current node
    val index = mutable.Map.empty[A, Int] //index of each node
    val lowLink = mutable.Map.empty[A, Int] //The smallest index reachable from the node
    val ret = mutable.Buffer.empty[mutable.Buffer[A]] //Keep track of SCC in graph
def visit(v: A): Unit = {
  //Set index and lowlink of node on first visit
  index(v) = index.size
  lowLink(v) = index(v)
  //Add to stack
  s += v
  if (src.exists(_.from == v)) {
    for (w <- src.find(e => e.from == v).head.to) {
      if (!index.contains(w)) { //Node is not explored yet
        //Perform DFS from node W
        visit(w)
        //Update the lowlink value of v so it has the value of the lowest node reachable from itself and from node w
        lowLink(v) = math.min(lowLink(w), lowLink(v))
      } else if (s.contains(w)) {
        // Node w is on the stack meaning - it means there is a path from w to v
        // and since node w is a neighbor to node v there is also a path from v to w
        lowLink(v) = math.min(lowLink(v), index(w))
      }
    }
  }
  //The lowlink value haven't been updated meaning it is the root of a cycle/SCC
  if (lowLink(v) == index(v)) {
    //Add the elements to the cycle that has been added to the stack and whose lowlink has been updated by node v's lowlink
    //This is the elements on the stack that is placed behind v
    val n = s.length - s.indexOf(v)
    ret += s.takeRight(n)
    //Remove these elements from the stack
    s.dropRightInPlace(n)
  }
}

//Perform a DFS from  all no nodes that hasn't been explored
src.foreach(v => if (!index.contains(v.from)) visit(v.from))
ret
  }

  // A cycle exist if there is a SCC with at least two components
  lazy val hasCycle: Boolean = trajan.exists(_.size >= 2)
  lazy val trajanCycle: Iterable[Seq[A]] = trajan.filter(_.size >= 2).distinct.map(_.toSeq).toSeq
  lazy val topologicalSortedEdges: Seq[Edge[A]] =
    if (hasCycle) Seq[Edge[A]]()
    else trajan.flatten.reverse.flatMap(x => src.find(_.from == x)).toSeq
}