end
# A `MapIterator` over a `HashMap`.
-class HashMapIterator[K, V]
+private class HashMapIterator[K, V]
super MapIterator[K, V]
redef fun is_ok do return _node != null
end
# The map to iterate on
- private var map: HashMap[K, V]
+ var map: HashMap[K, V]
# The current node
- private var node: nullable HashMapNode[K, V] = null
+ var node: nullable HashMapNode[K, V] = null
init
do
end
# All kinds of array-based text representations.
-abstract class FlatText
+private abstract class FlatText
super Text
# Underlying C-String (`char*`)
#
# Warning : Might be void in some subclasses, be sure to check
# if set before using it.
- private var items: NativeString is noinit
+ var items: NativeString is noinit
# Returns a char* starting at position `first_byte`
#
#
# As always, do not modify the content of the String in C code, if this is what you want
# copy locally the char* as Nit Strings are immutable.
- private fun fast_cstring: NativeString is abstract
+ fun fast_cstring: NativeString is abstract
redef var length = 0
redef class FlatText
- private fun first_byte: Int do return 0
+ fun first_byte: Int do return 0
- private fun last_byte: Int do return _bytelen - 1
+ fun last_byte: Int do return _bytelen - 1
# Cache of the latest position (char) explored in the string
- private var position: Int = 0
+ var position: Int = 0
# Cached position (bytes) in the NativeString underlying the String
- private var bytepos: Int = 0
+ var bytepos: Int = 0
# Index of the character `index` in `_items`
- private fun char_to_byte_index(index: Int): Int do
+ fun char_to_byte_index(index: Int): Int do
var ln = length
assert index >= 0
assert index < ln
# This enables a double-optimization in `escape_to_c` since if this
# method returns 0, then `self` does not need escaping and can be
# returned as-is
- protected fun chars_to_escape_to_c: Int do
+ fun chars_to_escape_to_c: Int do
var its = _items
var max = last_byte
var pos = first_byte
do
var l = length
if l == 0 then return ""
- if l == 1 then if self[0] == null then return "" else return self[0].to_s
- var its = _items
+ var its = _items.as(not null)
+ var first = its[0]
+ if l == 1 then if first == null then return "" else return first.to_s
var na = new NativeArray[String](l)
var i = 0
var sl = 0
# g.add_arcs([[1,2],[2,1],[2,3],[3,4],[4,5],[5,3]])
# for component in g.strongly_connected_components.to_partitions
# do
-# print component
+# print component
# end
# # Prints [1,2] and [3,4,5]
# ~~~
# g.add_arc(0, 2)
# g.add_arc(1, 2)
# for arc in g.arcs_iterator do
- # assert g.has_arc(arc[0], arc[1])
+ # assert g.has_arc(arc[0], arc[1])
# end
# ~~~
fun arcs_iterator: Iterator[Array[V]] do return new ArcsIterator[V](self)
# g.add_arc(1, 3)
# g.add_arc(2, 3)
# for arc in g.incoming_arcs(3) do
- # assert g.is_predecessor(arc[0], arc[1])
+ # assert g.is_predecessor(arc[0], arc[1])
# end
# ~~~
fun incoming_arcs(u: V): Collection[Array[V]]
# g.add_arc(2, 3)
# g.add_arc(1, 2)
# for arc in g.outgoing_arcs(1) do
- # assert g.is_successor(arc[1], arc[0])
+ # assert g.is_successor(arc[1], arc[0])
# end
# ~~~
fun outgoing_arcs(u: V): Collection[Array[V]]
return s
end
+ # Open Graphviz with `self.to_dot`.
+ #
+ # Mainly used for debugging.
+ fun show_dot do
+ var f = new ProcessWriter("dot", "-Txlib")
+ f.write to_dot
+ f.close
+ end
+
## ------------ ##
## Neighborhood ##
## ------------ ##
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Add PageRank computation for vertices in Digraph.
+module pagerank
+
+import graphs::digraph
+
+redef class Digraph[V]
+
+ # Compute PageRank for each vertex
+ #
+ # Details of the algorithm can be found in:
+ # > L. Page, S. Brin, R. Motwani, and T.Winograd.
+ # > **The pagerank citation ranking: Bringing order to the web.**
+ # > *Technical report, Stanford Digital Library Technologies Project, 1998*
+ #
+ # Example:
+ # ~~~
+ # var g = new HashDigraph[String]
+ # g.add_arc("A", "B")
+ # g.add_arc("A", "C")
+ # g.add_arc("B", "C")
+ # g.add_arc("C", "A")
+ # g.add_arc("D", "C")
+ #
+ # assert g.pagerank.join(", ", ":") == "A:1.488, B:0.782, C:1.575, D:0.15"
+ # ~~~
+ fun pagerank: PRMap[V] do
+ # `d` constant such as `initial_pagerank(node) == (1 - d) != 0`
+ var d = 0.85 # commonly-choosen value
+ # Init each node page rank with an initial_value
+ var values = new PRMap[V]
+ var vertices = self.vertices
+ for v in vertices do values[v] = 1.0 - d
+ # Compute page rank until convergence
+ var prev = new PRMap[V]
+ while not values.is_approx(prev, 0.001) do
+ prev = new PRMap[V].from(values)
+ for v in vertices do
+ var in_pr = 0.0
+ for o in predecessors(v) do
+ in_pr += values[o] / out_degree(o).to_f
+ end
+ values[v] = (1.0 - d) + d * in_pr
+ end
+ end
+ return values
+ end
+end
+
+# Map each Vertice of a Digraph to it's PageRank.
+#
+# See: `Digraph::pagerank`.
+class PRMap[V]
+ super HashMap[V, Float]
+
+ # Init `self` by copying `other` values.
+ init from(other: PRMap[V]) do
+ init
+ for k, v in other do self[k] = v
+ end
+
+ # Is `self` approximately equal to another PRMap?
+ #
+ # `self` is approximately equal to `o` if `o` contains all the key from `self`
+ # with the same values.
+ #
+ # Values equality is based on `Float::is_approx` with `precision`.
+ fun is_approx(o: SELF, precision: Float): Bool do
+ for k1, v1 in self do
+ if not o.has_key(k1) then return false
+ if not v1.is_approx(o[k1], precision) then return false
+ end
+ return true
+ end
+end
import metrics_base
import mclasses_metrics
+import mmodules_metrics
import modelize
redef class ToolContext
end
end
+# Module Branch Mean Size
+# mbms(module) = |mclassdefs(module)| / (DIT(module) + 1)
+class MBMS
+ super MModuleMetric
+ super FloatMetric
+ redef fun name do return "mbms"
+ redef fun desc do return "branch mean size, mean number of class definition available among ancestors"
+
+ redef fun collect(mmodules) do
+ for mmodule in mmodules do
+ var totc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+ totc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ var ditc = mmodule.in_importation.depth
+ values[mmodule] = totc.to_f / (ditc + 1).to_f
+ end
+ end
+end
+
# Class Novelty Index
# cnvi = |LocS(class)| / cbms(parents(class))
class CNVI
end
end
+# Module Novelty Index
+# mnvi = |LocS(module)| / mbms(parents(module))
+class MNVI
+ super MModuleMetric
+ super FloatMetric
+ redef fun name do return "mnvi"
+ redef fun desc do return "module novelty index, contribution of the module to its branch in term of introductions"
+
+ redef fun collect(mmodules) do
+ var mbms = new MBMS
+ for mmodule in mmodules do
+ # compute branch mean size
+ var parents = mmodule.in_importation.direct_greaters
+ if parents.length > 0 then
+ mbms.clear
+ mbms.collect(new HashSet[MModule].from(parents))
+ # compute module novelty index
+ var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+ locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ values[mmodule] = locc.to_f / mbms.avg
+ else
+ values[mmodule] = 0.0
+ end
+ end
+ end
+end
+
# Class Novelty Score
# cnvs = |LocS(class)| x nvi
class CNVS
end
end
+# Module Novelty Score
+# mnvs = |LocS(module)| x nvi
+class MNVS
+ super MModuleMetric
+ super FloatMetric
+ redef fun name do return "mnvs"
+ redef fun desc do return "module novelty score, importance of the contribution of the module to its branch"
+
+ redef fun collect(mmodules) do
+ var mnvi = new MNVI
+ mnvi.collect(mmodules)
+ for mmodule in mmodules do
+ var locc = mmodule.collect_intro_mclassdefs(protected_visibility).length
+ locc += mmodule.collect_redef_mclassdefs(protected_visibility).length
+ values[mmodule] = mnvi.values[mmodule] * locc.to_f
+ end
+ end
+end
+
redef class MClass
# the set of redefition that call to super
fun extended_mproperties(min_visibility: MVisibility): Set[MProperty] do
return false
end
end
-
fun values: RES is abstract
# Collect metric values on elements
- fun collect(elements: Set[ELM]) is abstract
+ fun collect(elements: Collection[ELM]) is abstract
# The value calculated for the element
fun [](element: ELM): VAL do return values[element]
redef fun sum do
var sum = 0.0
- for v in values.values do sum += v
+ for v in values.values do
+ if v.is_nan then continue
+ sum += v
+ end
return sum
end
redef fun std_dev do
var sum = 0.0
for value in values.values do
+ if value.is_nan then continue
sum += (value - avg).pow(2.to_f)
end
return (sum / values.length.to_f).sqrt