A JVM implementation of the Pair Adjacent Violators algorithm for isotonic regression

Overview

Pair Adjacent Violators

status stable Awesome Kotlin Badge Travis coverage 89%

Overview

An implementation of the Pair Adjacent Violators algorithm for isotonic regression. Written in Kotlin but usable from Java or any other JVM language.

Note this algorithm is also known as "Pool Adjacent Violators".

What is "Isotonic Regression" and why should I care?

Imagine you have two variables, x and y, and you don't know the relationship between them, but you know that if x increases then y will increase, and if x decreases then y will decrease. Alternatively it may be the opposite, if x increases then y decreases, and if x decreases then y increases.

Examples of such isotonic or monotonic relationships include:

  • x is the pressure applied to the accelerator in a car, y is the acceleration of the car (acceleration increases as more pressure is applied)
  • x is the rate at which a web server is receiving HTTP requests, y is the CPU usage of the web server (server CPU usage will increase as the request rate increases)
  • x is the price of an item, and y is the probability that someone will buy it (this would be a decreasing relationship, as x increases y decreases)

These are all examples of an isotonic relationship between two variables, where the relationship is likely to be more complex than linear.

So we know the relationship between x and y is isotonic, and let's also say that we've been able to collect data about actual x and y values that occur in practice.

What we'd really like to be able to do is estimate, for any given x, what y will be, or alternatively for any given y, what x would be required.

But of course real-world data is noisy, and is unlikely to be strictly isotonic, so we want something that allows us to feed in this raw noisy data, figure out the actual relationship between x and y, and then use this to allow us to predict y given x, or to predict what value of x will give us a particular value of y. This is the purpose of the pair-adjacent-violators algorithm.

...and why should I care?

Using the examples I provide above:

  • A self-driving car could use it to learn how much pressure to apply to the accelerator to give a desired amount of acceleration
  • An autoscaling system could use it to help predict how many web servers they need to handle a given amount of web traffic
  • A retailer could use it to choose a price for an item that maximizes their profit (aka "yield optimization")

Isotonic regression in online advertising

If you have an hour to spare, and are interested in learning more about how online advertising works - you should check out this lecture that I gave in 2015 where I explain how we were able to use pair adjacent violators to solve some fun problems.

A picture is worth a thousand words

Here is the relationship that PAV extracts from some very noisy input data where there is an increasing relationship between x and y:

PAV in action

Features

  • Tries to do one thing and do it well with minimal bloat, no external dependencies (other than Kotlin's stdlib)
  • Very thorough unit tests, achieving approx 75% mutation test coverage
  • Employs an isotonic spline algorithm for smooth interpolation
  • Fairly efficient implementation without compromizing code readability
  • While implemented in Kotlin, works nicely from Java and other JVM languages
  • Supports reverse-interpolation
  • Will intelligently extrapolate to compute y for values of x greater or less than those used to build the PAV model

Usage

Adding library dependency

You can use this library by adding a dependency for Gradle, Maven, SBT, Leiningen or another Maven-compatible dependency management system thanks to Jitpack:

Basic usage from Kotlin

import com.github.sanity.pav.PairAdjacentViolators
import com.github.sanity.pav.PairAdjacentViolators.*
// ...
val inputPoints = listOf(Point(3.0, 1.0), Point(4.0, 2.0), Point(5.0, 3.0), Point(8.0, 4.0))
val pav = PairAdjacentViolators(inputPoints)
val interpolator = pav.interpolator()
println("Interpolated: ${interpolator(6.0)}")

Basic usage from Java

import com.github.sanity.pav.*;
import com.github.sanity.pav.PairAdjacentViolators.*;
import kotlin.jvm.functions.*;
import java.util.*;

public class PAVTest {
    public static void main(String[] args) {
        List<Point> points = new LinkedList<>();
        points.add(new Point(0.0, 0.0));
        points.add(new Point(1.0, 1.0));
        points.add(new Point(2.0, 3.0));
        points.add(new Point(3.0, 5.0));
        PairAdjacentViolators pav = new PairAdjacentViolators(points);
        final Function1<Double, Double> interpolator = pav.interpolator();
        for (double x=0; x<3; x+=0.1) {
            System.out.println(x+"\t"+interpolator.invoke(x));
        }
    }
}

Questions/Feedback

Please ask questions, report bugs, request features etc via Github Issues, you're also more than welcome to submit pull requests.

License

Released under the LGPL version 3 by Ian Clarke.

See also

Comments
  • java.io.NotSerializableException

    java.io.NotSerializableException

    Hello, i'm using version 1.2.1 and jdk8.

    The code in gist throws java.io.NotSerializableException: com.github.sanity.pav.PairAdjacentViolators.

    Is it ok/hard to fix?

    opened by mikhailusachev 5
  • Benchmarks

    Benchmarks

    I want to suggest use JMH for benchmarking. It's a lot better, because JMH knows a lot about JVM, and properly warm up code, etc.

    Maybe this video is good start.

    I can help with project configuration and maybe with rewriting current benchmark to JMH.

    enhancement 
    opened by IRus 3
  • Exclude some files

    Exclude some files

    Hi!

    Looks like you committed few directories like:

    .idea
    build
    .gradle 
    

    which useless for project users and auto-generated by ide or build tool. I suggest clean up this.

    opened by IRus 2
  • Support extrapolation

    Support extrapolation

    Currently, the interpolation is assumed to be flat for any point below the lowest x control point or above the highest x control point.

    A better approach might be to extrapolation based on the first two or last two control points.

    enhancement 
    opened by sanity 1
  • Update gradle to 3.0 (from 2.13), added gradle's wrapper jar.

    Update gradle to 3.0 (from 2.13), added gradle's wrapper jar.

    I tried to compile project locally via gradlew, and get following error:

    ./gradlew clean build
    Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain
    

    This is because of lack of gradle jar in gradle/wrapper directory.

    I added this jar and update gradle to latest version/

    opened by IRus 0
  • Use of mutation testing in pairAdjacentViolators - Help needed

    Use of mutation testing in pairAdjacentViolators - Help needed

    Hello there!

    My name is Ana. I noted that you use the mutation testing tool in the project. I am a postdoctoral researcher at the University of Seville (Spain), and my colleagues and I are studying how mutation testing tools are used in practice. With this aim in mind, we have analysed over 3,500 public GitHub repositories using mutation testing tools, including yours! This work has recently been published in a journal paper available at https://link.springer.com/content/pdf/10.1007/s10664-022-10177-8.pdf.

    To complete this study, we are asking for your help to understand better how mutation testing is used in practice, please! We would be extremely grateful if you could contribute to this study by answering a brief survey of 21 simple questions (no more than 6 minutes). This is the link to the questionnaire https://forms.gle/FvXNrimWAsJYC1zB9.

    Drop me an e-mail if you have any questions or comments ([email protected]). Thank you very much in advance!!

    opened by belene 0
Releases(1.4.16)
Owner
Ian Clarke
Degree in CS & AI. Creator of freenetproject.org, kweb.io, 33mail.com.
Ian Clarke
Android library to achieve in an easy way, the behaviour of the home page in the Expedia app, with a pair of auto-scroll circular parallax ListViews.

ListBuddies This library is not maintained anymore and there will be no further releases Android library of a pair of auto-scroll circular parallax Li

JPARDOGO 970 Dec 29, 2022
Tool for create complex morphing animations using VectorDrawables (allows morphing between any pair of SVG images)

VectAlign VectAlign (a.k.a. VectorDrawableAlign) is a developer's tool which automagically aligns two VectorDrawable "pathData" strings (or SVG images

Stefano Bonetta 2k Dec 29, 2022
A pair of applications provide a direct means of integrating with one another via application programming interfaces (APIs)

What is a native integration? It's when a pair of applications provide a direct means of integrating with one another via application programming interfaces (APIs). Once integrated, data can flow between the apps and become more readily available to your employees.

Behruz Hurramov 2 Jan 17, 2022
MiHawk 🦅👁️ is simple and secure 🔒 Android Library to store and retrieve pair of key-value data with encryption , internally it use jetpack DataStore Preferences 💽 to store data.

MiHawk MiHawk ?? ??️ is simple and secure ?? Android Library to store and retrieve pair of key-value data with encryption , internally it use jetpack

Nedal Hasan Ibrahem 5 Sep 3, 2022
Lambë Language 7 Dec 21, 2022
A library that gives full control over text related technologies such as bidirectional algorithm, open type shaping, text typesetting and text rendering

Tehreer-Android Tehreer is a library which gives full control over following text related technologies. Bidirectional Algorithm OpenType Shaping Engin

Tehreer 61 Dec 15, 2022
With Viola android face detection library, you can detect faces in a bitmap, crop faces using predefined algorithm and get additional information from the detected faces.

Viola Viola android face detection library detects faces automatically from a bitmap, crop faces using the predefined algorithms, and provides supplem

Darwin Francis 58 Nov 1, 2022
Android Camera Application for Exposure Fusion Algorithm and more

Android Camera Application for Exposure Fusion Algorithm and more

Seri Lee 10 Nov 14, 2021
Android app to test various cryptography algorithm.

CryptographyLesson Introduction This android app shows how cryptographic algorithm works. You can encrypt or decrypt messages and try different algori

null 3 Mar 21, 2022
Android app to test various cryptography algorithm.

This android app shows how cryptographic algorithm works. You can encrypt or decrypt messages and try different algorithms. Powered by Bouncy Castle this app supports AES, Serpent, Blowfish and many more :)

null 3 Mar 21, 2022
Acme-app - App to display the best routes for drivers based on a secret algorithm

Acme App App to display the best routes for drivers based on a "secret" algorith

Pablo Baxter 0 Jan 9, 2022
Algorithm for mutual exclusion in a bidirectional ring network topology with unreliable communication channels.

Algorithm for mutual exclusion in a bidirectional ring network topology with unreliable communication channels

Bartlomiej Szal 0 Jan 13, 2022
Documentation and implementations of a recursive procedural generation algorithm authored by Christopher Ravosa.

Recursive-Dungeon-Generation This repository contains implementations of a recursive algorithm, authored by Christopher Ravosa, for generating dungeon

Christopher Ravosa 1 Mar 30, 2022
An Android app that gives you a password generated by a given phrase with a custom algorithm, it also has password and biometric security.

An Android app that gives you a password generated by a given phrase with a custom algorithm, it also has password and biometric security.

Marcos Ariel Paccor 1 May 23, 2022
Simple application with some famous graph algorithm implemented by Jetpack Compose framework

GraphAlgorithm This Application was implemented by Jetpack Compose framework. The dagger-hilt library was used for dependency injection and Room libra

Amirreza lotfi 8 Aug 17, 2022
RCZ algorithm in kotlin (update version)

RCZEncryptationKT RCZ Encrypt uses maps to encrypt your string this use ALPHABYTE to to view the bytearray of encoded strings This use random chars by

Halq 5 Oct 11, 2022
Archimedes's implementation for the Java Virtual Machine (JVM)

Archimedes Give me a place to stand, and I shall move the earth. Archimedes's implementation for the Java Virtual Machine (JVM) Building From Source T

Archimedes 24 Aug 20, 2022
Redux implementation for Kotlin (supports multiplatform JVM, native, JS, WASM)

Redux-Kotlin ![badge][badge-ios] A redux standard for Kotlin that supports multiplatform projects. Full documentation at http://reduxkotlin.org. Misso

Redux-Kotlin 301 Dec 25, 2022
An implementation of MediatR on JVM for Spring using Kotlin coroutines

Kpring MediatR In this project, an attempt has been made to implement the mediator pattern on the JVM with simplicity using Kotlin with native corouti

Mahdi Bohloul 4 Aug 6, 2022
[] Action bar implementation which uses the native action bar on Android 4.0+ and a custom implementation on pre-4.0 through a single API and theme.

DEPRECATED ActionBarSherlock is deprecated. No more development will be taking place. For an up-to-date action bar backport use AppCompat. Thanks for

Jake Wharton 7.1k Dec 24, 2022