Questo è un follow-up di one dei miei post precedenti.La complessità di scala.xml.RuleTransformer è davvero esponenziale?
Ho cercato di capire perché le prestazioni dello RuleTransformer sono così scadenti. Ora credo che sia così lento perché la sua complessità è O (2 n), dove n è l'altezza dell'albero XML di input.
Supponiamo che ho bisogno di rinominare tutte le etichette di tutti gli elementi di etichettare "b":
import scala.xml._, scala.xml.transform._
val rule: RewriteRule = new RewriteRule() {
override def transform(node: Node): Seq[Node] = node match {
case e: Elem => e.copy(label = "b")
case other => other
}
}
def trans(node: Node): Node = new RuleTransformer(rule).apply(node)
Contiamo quante volte i transform
visite ogni nodo di ingresso <a3><a2><a1/></a2></a3>
.
Per contare le visite aggiungiamo un buffer visited
, inizialo all'inizio, memorizza i nodi visitati e stampalo alla fine.
import scala.collection.mutable.ListBuffer
// buffer to store visited nodes
var visited: ListBuffer[Node] = ListBuffer[Node]()
val rule: RewriteRule = new RewriteRule() {
override def transform(n: Node): Seq[Node] = {
visited append (n) // count this visit
n match {
case e: Elem => e.copy(label = "b")
case other => other
}
}
}
def trans(node: Node): Node = {
visited = ListBuffer[Node]() // init the buffer
val r = new RuleTransformer(rule).apply(node)
// print visited nodes and numbers of visits
println(visited.groupBy(identity).mapValues(_.size).toSeq.sortBy(_._2))
r
}
Ora corriamo in REPL e vedere il visited
scala> val a3 = <a3><a2><a1/></a2></a3>
a3: scala.xml.Elem = <a3><a2><a1/></a2></a3>
scala> trans(a3)
ArrayBuffer((<a3><b><b/></b></a3>,2), (<a2><b/></a2>,4), (<a1/>,8))
res1: scala.xml.Node = <b><b><b/></b></b>
Così a1
è visitato otto volte.
Se trasformiamo <a4><a3><a2><a1/></a2></a3></a4>
poi a1
sarà visitata 16 volte, per <a5><a4><a3><a2><a1/></a2></a3></a4></a5>
- 32, ecc Quindi la complessità sembra esponenziale.
Ha senso? Come lo dimostreresti analizzando lo code?
Grazie per l'analisi. Concordo sul fatto che poiché 'transform (n: Node)' è invocato _twice_ per ogni nodo, la ricorsione è 'T (n) = 2 * T (n - 1)' e quindi la complessità complessiva è esponenziale. – Michael
Ora sto lentamente iniziando a capire che _come_ scarsa è la qualità della libreria 'scala-xml'. – Michael
@ Michael, d'accordo, stavo cercando di trovare qualsiasi discussione intorno a questi o alla cronologia di github per vedere qualsiasi motivo per il modo in cui è codificato (come volevo riutilizzare i nodi o conservare l'ordine, tipo di supposizione) ma non ho trovato nessuno. – Biswanath