1 | package com.github.sanity.pav | |
2 | ||
3 | import com.github.sanity.pav.PairAdjacentViolators.InterpolationStrategy.SPLINE | |
4 | import com.github.sanity.pav.spline.MonotoneSpline | |
5 | import java.io.Serializable | |
6 | import java.util.* | |
7 | ||
8 | /** | |
9 | * Implements the "pair adjacent violators" algorithm, also known as "pool adjacent violators", for isotonic regression. | |
10 | */ | |
11 | ||
12 | ||
13 | class PairAdjacentViolators @JvmOverloads constructor(originalPoints: Iterable<Point>, mode: PAVMode = PAVMode.INCREASING) : Serializable { | |
14 | ||
15 | companion object { | |
16 | private const val serialVersionUID: Long = -5624398625406 | |
17 | } | |
18 | ||
19 | /** | |
20 | * The points after the regression, should either be increasing or decreasing depending | |
21 | * on how the PairAdjacentViolators object is configured. | |
22 | */ | |
23 |
1
1. getIsotonicPoints : mutated return of Object value for com/github/sanity/pav/PairAdjacentViolators::getIsotonicPoints to ( if (x != null) null else throw new RuntimeException ) → KILLED |
val isotonicPoints: ArrayList<Point> |
24 | ||
25 | init { | |
26 | val points: PairSubstitutingDoublyLinkedList<Point> = PairSubstitutingDoublyLinkedList.createFromList(originalPoints.sortedBy { it.x }) | |
27 |
1
1. |
points.iterate { cursor -> |
28 | val previous = cursor.previousValue | |
29 | val next = cursor.nextValue | |
30 |
1
1. invoke : negated conditional → KILLED |
if (previous != null) { |
31 | val shouldMerge = | |
32 | previous.x == next.x || ( | |
33 |
2
1. invoke : negated conditional → KILLED 2. invoke : negated conditional → KILLED |
when (mode) { |
34 |
2
1. invoke : changed conditional boundary → KILLED 2. invoke : negated conditional → KILLED |
PAVMode.INCREASING -> previous.y >= next.y |
35 |
2
1. invoke : changed conditional boundary → KILLED 2. invoke : negated conditional → KILLED |
PAVMode.DECREASING -> previous.y <= next.y |
36 | }) | |
37 |
1
1. invoke : negated conditional → KILLED |
if (shouldMerge) { |
38 | previous.merge(next) | |
39 | } else { | |
40 | null | |
41 | } | |
42 | } else { | |
43 | null | |
44 |
1
1. invoke : mutated return of Object value for com/github/sanity/pav/PairAdjacentViolators$1::invoke to ( if (x != null) null else throw new RuntimeException ) → KILLED |
} |
45 | } | |
46 | ||
47 | isotonicPoints = points.toArrayList() | |
48 | } | |
49 | ||
50 | @JvmOverloads fun interpolator(strategy: InterpolationStrategy = SPLINE): (Double) -> Double { | |
51 | when (strategy) { | |
52 |
1
1. interpolator : mutated return of Object value for com/github/sanity/pav/PairAdjacentViolators::interpolator to ( if (x != null) null else throw new RuntimeException ) → KILLED |
SPLINE -> return { |
53 |
1
1. invoke : replaced return of double value with -(x + 1) for com/github/sanity/pav/PairAdjacentViolators$interpolator$1::invoke → KILLED |
MonotoneSpline(isotonicPoints).interpolate(it) |
54 | } | |
55 | } | |
56 | } | |
57 | ||
58 | @JvmOverloads fun inverseInterpolator(strategy: InterpolationStrategy = SPLINE): (Double) -> Double { | |
59 | when (strategy) { | |
60 |
1
1. inverseInterpolator : mutated return of Object value for com/github/sanity/pav/PairAdjacentViolators::inverseInterpolator to ( if (x != null) null else throw new RuntimeException ) → KILLED |
SPLINE -> return { |
61 | val spline = MonotoneSpline(isotonicPoints.map {Point(it.y, it.x)}) | |
62 |
1
1. invoke : replaced return of double value with -(x + 1) for com/github/sanity/pav/PairAdjacentViolators$inverseInterpolator$1::invoke → KILLED |
spline.interpolate(it) |
63 | } | |
64 | } | |
65 | } | |
66 | ||
67 | enum class InterpolationStrategy { | |
68 | SPLINE | |
69 | } | |
70 | ||
71 | enum class PAVMode { | |
72 | INCREASING, DECREASING | |
73 | } | |
74 | } | |
Mutations | ||
23 |
1.1 |
|
27 |
1.1 |
|
30 |
1.1 |
|
33 |
1.1 2.2 |
|
34 |
1.1 2.2 |
|
35 |
1.1 2.2 |
|
37 |
1.1 |
|
44 |
1.1 |
|
52 |
1.1 |
|
53 |
1.1 |
|
60 |
1.1 |
|
62 |
1.1 |
|
77 |
1.1 |