Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f20f569
randomly generate graphs with max given indegree
koksal Sep 17, 2016
cd5fd7e
random time series data generation
koksal Sep 17, 2016
a8a6843
harness to run scalability analysis
koksal Sep 17, 2016
392be4a
fix PIN parsing
koksal Sep 17, 2016
378eba8
add source vertex to random graph gen
koksal Sep 17, 2016
d988478
cached graph neighbor computation
koksal Sep 17, 2016
cdadc20
fix
koksal Sep 17, 2016
b37f4bd
purely random graph generation for efficiency
koksal Sep 18, 2016
26ff80d
basic graph metrics to match simulated data to real data
koksal Sep 18, 2016
5a5ae7c
harness to run stats
koksal Sep 18, 2016
86e93f4
fix test
koksal Sep 18, 2016
e0b4516
add measurement significance probability parameter
koksal Sep 18, 2016
e6fe954
add missing file
koksal Sep 18, 2016
a1f5505
time series data coverage stats
koksal Sep 18, 2016
4ff379d
measure performance w/ replicates
koksal Sep 18, 2016
b457e83
random seed
koksal Sep 18, 2016
5454b99
print time series-specific stats
koksal Sep 19, 2016
cf049e9
multiple phosphosite simulation
koksal Oct 3, 2016
9708cb5
test scalability with exponentially growing sizes
koksal Oct 3, 2016
3456716
use peptide mapping in scalability analysis runs
koksal Oct 3, 2016
95306ab
remove invalid invariant and prune dead code
koksal Oct 3, 2016
2a25435
run 3 simulation replicates, and change input size limit
koksal Oct 4, 2016
fdcff15
clean up unused random graph generation code
koksal Jun 25, 2017
fb1bdcc
correct stale comment
koksal Jun 25, 2017
fadd650
clean up unused exception
koksal Jun 25, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
*.swp
*.iml
.idea
.DS_Store
sbt
project/project
project/target
target
logs
12 changes: 10 additions & 2 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ object ApplicationBuild extends Build {

showSuccess := false,

resolvers += "sonatype-public" at "https://oss.sonatype.org/content/groups/public"
resolvers ++= Seq(
"sonatype-public" at
"https://oss.sonatype.org/content/groups/public",
"Sonatype Snapshots" at
"https://oss.sonatype.org/content/repositories/snapshots/",
"Sonatype Releases" at
"https://oss.sonatype.org/content/repositories/releases/"
)
)

val coreSettings = commonSettings ++ Seq(
Expand All @@ -25,7 +32,8 @@ object ApplicationBuild extends Build {

libraryDependencies ++= Seq(
"org.scalatest" % "scalatest_2.11" % "2.2.4" % "test",
"com.github.scopt" %% "scopt" % "3.3.0"
"com.github.scopt" %% "scopt" % "3.3.0",
"org.scalanlp" %% "breeze" % "0.12"
),

mainClass in (Compile, run) := Some("tps.Main"),
Expand Down
7 changes: 7 additions & 0 deletions scripts/run-scalability-analysis
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

sbt "project tps-core" "run-main tps.evaluation.ScalabilityAnalysis \
--network data/networks/directed-pin-with-resource-edges.tsv \
--source EGF_HUMAN \
--threshold 0.01
"
2 changes: 0 additions & 2 deletions tps-core/src/main/scala/tps/ArgHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package tps

import tps.util.LogUtils

import java.io.File

object ArgHandling {
def parseOptions(args: Array[String]) = {
val opts = new Options()
Expand Down
42 changes: 21 additions & 21 deletions tps-core/src/main/scala/tps/Graphs.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package tps

import tps.util.LogUtils._

object Graphs {

case class Vertex(id: String) extends Serializable {
Expand Down Expand Up @@ -33,23 +31,24 @@ object Graphs {
assert(v1.id <= v2.id)
}

private var neighborMap = Map[Vertex, Set[Vertex]]().withDefaultValue(
Set.empty[Vertex])
for (e <- E) {
neighborMap += e.v1 -> (neighborMap(e.v1) + e.v2)
neighborMap += e.v2 -> (neighborMap(e.v2) + e.v1)
}

override def toString = {
V.mkString("V = {", ", ", "}") + "\n" +
E.mkString("E = {", ", ", "}") + "\n" +
sources.mkString("SRC = {", ", ", "}")
}

def neighbors(v: Vertex): Set[Vertex] = {
E collect {
case Edge(v1, v2) if v1 == v => v2
case Edge(v1, v2) if v2 == v => v1
}
}
def neighbors(v: Vertex): Set[Vertex] = neighborMap(v)

def incidentEdges(v: Vertex): Set[Edge] = {
E filter {
case Edge(v1, v2) => v1 == v || v2 == v
}
val ns = neighbors(v)
ns.map(n => lexicographicEdge(n, v))
}

def contains(e: Edge): Boolean = {
Expand Down Expand Up @@ -88,20 +87,18 @@ object Graphs {
distances += v -> 0
}

while (!toProcess.isEmpty) {
while (toProcess.nonEmpty) {
distance += 1
val nextStep = toProcess.flatMap{ v =>
val nextStep = toProcess.flatMap { v =>
this.neighbors(v)
}.filter{ v =>
!alreadySeen.contains(v)
}
}.diff(alreadySeen)

for (v <- nextStep) {
distances += v -> distance
}
for (v <- nextStep) {
distances += v -> distance
}

alreadySeen ++= nextStep
toProcess = nextStep
alreadySeen ++= nextStep
toProcess = nextStep
}

distances
Expand Down Expand Up @@ -145,6 +142,9 @@ object Graphs {
}
}

def lexicographicEdge(v1: Vertex, v2: Vertex): Edge =
GraphParsing.lexicographicEdge(v1.id, v2.id)

private def reverseDirection(d: EdgeDirection): EdgeDirection = d match {
case Forward => Backward
case Backward => Forward
Expand Down
9 changes: 5 additions & 4 deletions tps-core/src/main/scala/tps/PINParser.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package tps

import Graphs._
import GraphParsing._

object PINParser {
def run(f: java.io.File): DirectedGraph = {
Expand All @@ -10,11 +9,13 @@ object PINParser {
val Seq(id1, id2, weight, orientation) = tuple
orientation match {
case "U" =>
lexicographicEdge(id1, id2) -> Set[EdgeDirection](Forward, Backward)
GraphParsing.lexicographicEdge(id1, id2) -> Set[EdgeDirection](
Forward, Backward)
case "D" =>
lexicographicEdge(id1, id2) -> Set[EdgeDirection](lexicographicForwardDirection(id1, id2))
GraphParsing.lexicographicEdge(id1, id2) -> Set[EdgeDirection](
GraphParsing.lexicographicForwardDirection(id1, id2))
}
}
aggregateLabels(pairs)
GraphParsing.aggregateLabels(pairs)
}
}
8 changes: 4 additions & 4 deletions tps-core/src/main/scala/tps/ReferenceParser.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package tps

import Graphs._
import GraphParsing._

object ReferenceParser {
def run(f: java.io.File): (SignedDirectedGraph, Map[Edge, String]) = {
Expand All @@ -12,7 +11,7 @@ object ReferenceParser {

val tuples = data.tuples.collect{ case tuple if tuple.size >= 7 =>
val Seq(src, tgt, lra, lri, rla, rli, rest @ _*) = tuple
val edge = lexicographicEdge(src, tgt)
val edge = GraphParsing.lexicographicEdge(src, tgt)

assert(!evidencePerEdge.isDefinedAt(edge))
evidencePerEdge += edge -> rest.mkString(", ")
Expand All @@ -28,11 +27,12 @@ object ReferenceParser {
if (labelValue(rla)) originalLabels += ActiveEdge(Backward, Activating)
if (labelValue(rli)) originalLabels += ActiveEdge(Backward, Inhibiting)

val lexicOrientedLabels = originalLabels map { l => lexicographicLabel(src, tgt, l) }
val lexicOrientedLabels = originalLabels map { l =>
GraphParsing.lexicographicLabel(src, tgt, l) }

(edge, lexicOrientedLabels)
}

(aggregateLabels(tuples), evidencePerEdge)
(GraphParsing.aggregateLabels(tuples), evidencePerEdge)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object SignedDirectedGraphParser {
val data = new TSVSource(f, noHeaders = true).data
val pairs = data.tuples map { tuple =>
val Seq(id1, tpe, id2) = tuple
val edge = lexicographicEdge(id1, id2)
val edge = GraphParsing.lexicographicEdge(id1, id2)
tpe match {
case "N" => edge -> Set(
lexicographicActivation(id1, id2),
Expand Down
9 changes: 9 additions & 0 deletions tps-core/src/main/scala/tps/UndirectedGraphOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,13 @@ object UndirectedGraphOps {
}

def emptyGraph: UndirectedGraph = UndirectedGraph(Set.empty, Set.empty, Set.empty)

def fromDirectedGraph(g: DirectedGraph): UndirectedGraph = {
var V: Set[Vertex] = Set.empty
val E = g.keySet
for (e <- E) {
V ++= Set(e.v1, e.v2)
}
UndirectedGraph(V, E, Set.empty)
}
}
74 changes: 74 additions & 0 deletions tps-core/src/main/scala/tps/evaluation/GraphStats.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package tps.evaluation

import java.io.File

import tps.Graphs.UndirectedGraph
import tps.synthesis.Synthesis
import tps.{TimeSeries, UndirectedGraphParser}
import tps.util.MathUtils

/**
* Computes basic graph statistics
*/
object GraphStats {
def computeGraphStats(g: UndirectedGraph): Unit = {
// # nodes, # edges, avg degree, median degree
println(s"# vertices: ${g.V.size}")
println(s"# edges : ${g.E.size}")

val vertexDegrees = g.V.map(v => g.neighbors(v).size.toDouble)
println(s"Average vertex degree: ${MathUtils.mean(vertexDegrees)}")
println(s"Median vertex degree : ${MathUtils.median(vertexDegrees)}")
}

def computeDataCoverageStats(g: UndirectedGraph, ts: TimeSeries): Unit = {
val profileIds = ts.profiles.map(_.id).toSet
val verticesWithData = g.V.map(_.id).intersect(profileIds)
val coverageRatio = verticesWithData.size.toDouble / g.V.size
println(s"Ratio of vertices with data: ${coverageRatio}")
}

/**
* Prints the mean number of phosphosites per protein in the given graph.
*
* The graph and time series data are not expanded.
*/
def printMeanNbPhosphosites(
g: UndirectedGraph, ts: TimeSeries, ppm: Map[String, Set[String]]
): Unit = {
val phosphositeCardinalities = g.V.toSeq map { v =>
// get peptides that map to the protein
val matchingPeptides = ppm.filter{ case (pep, prots) =>
prots contains v .id }.keySet
val matchingProfiles = ts.profiles.filter{ p =>
matchingPeptides contains p.id
}
matchingProfiles.size
}

val mean = MathUtils.mean(phosphositeCardinalities.map(_.toDouble))
println(s"Mean number of phosphosites: $mean")
}

def computeProfileStats(
ts: TimeSeries,
firstScores: Map[String, Seq[Double]],
prevScores: Map[String, Seq[Double]],
threshold: Double
): Unit
= {
val nbSigMeasurements = ts.profiles map { p =>
Synthesis.nbSignificantMeasurements(p, firstScores, prevScores, threshold)
}
val med = MathUtils.median(nbSigMeasurements.map(_.toDouble))
println(s"Median number of significant time points: $med")
val mean = MathUtils.mean(nbSigMeasurements.map(_.toDouble))
println(s"Mean number of significant time points: $mean")
}

def main(args: Array[String]): Unit = {
val graphName = args(0)
val graph = UndirectedGraphParser.run(new File(graphName))
computeGraphStats(graph)
}
}
50 changes: 50 additions & 0 deletions tps-core/src/main/scala/tps/evaluation/ScalabilityAnalysis.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tps.evaluation

import tps._
import tps.simulation.{RandomGraphGenerator, RandomTimeSeriesGenerator}
import tps.synthesis.{Synthesis, SynthesisOptions}
import tps.util.{Stopwatch, TimingUtil}

/**
* Evaluates solver running time on randomly simulated data.
*/
object ScalabilityAnalysis {

private val MIN_GRAPH_SIZE = 1000
private val MAX_GRAPH_SIZE = 128000

private val SIGNIFICANCE_THRESHOLD = 0.01

def main(args: Array[String]): Unit = {
val resultReporter = new NoopReporter()

var size = MIN_GRAPH_SIZE
do {
println(s"Evaluating with size $size")

TimingUtil.timeReplicates(s"Scalability analysis for $size", 3) {
val g = RandomGraphGenerator.generateRandomGraph(size)
val ppm = RandomTimeSeriesGenerator.generateRandomPeptideProteinMap(g)
val ts = RandomTimeSeriesGenerator.generateRandomTimeSeries(ppm.keySet)
val scores = RandomTimeSeriesGenerator.generateSignificanceScores(ts)

Synthesis.run(
g,
ts,
scores,
scores,
Set.empty,
ppm,
g.sources map (_.id),
SIGNIFICANCE_THRESHOLD,
SynthesisOptions(),
resultReporter
)

println("Nb. phosphosites: " + ppm.keySet.size)
}

size = size * 2
} while (size <= MAX_GRAPH_SIZE)
}
}
44 changes: 44 additions & 0 deletions tps-core/src/main/scala/tps/simulation/RandomGraphGenerator.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tps.simulation

import tps.Graphs
import tps.Graphs.{Edge, UndirectedGraph, Vertex}

/**
* Generates a random graph of given size, according to a predetermined
* likelihood of choosing between adding a new node and adding a new edge to
* it.
*/
object RandomGraphGenerator {

private val RANDOM_SEED = 131161511
private val random = new scala.util.Random(RANDOM_SEED)

private val NODE_CREATION_PROBABILITY = 0.5

def generateRandomGraph(nbEdges: Int): UndirectedGraph = {
val src = Vertex("src")
var V = Set[Vertex](src)
var E = Set[Edge]()

var i = 0
while (E.size < nbEdges) {
val srcVertex = V.toIndexedSeq(random.nextInt(V.size))
val tgtVertex = if (random.nextDouble() < NODE_CREATION_PROBABILITY) {
// add a new node
i += 1
Vertex(s"v_$i")
} else {
// add an edge to an existing node
V.toIndexedSeq(random.nextInt(V.size))
}
// do not add self edges
if (srcVertex != tgtVertex) {
V += tgtVertex
E += Graphs.lexicographicEdge(srcVertex, tgtVertex)
}
}

UndirectedGraph(V, E, Set(src))
}

}
Loading