it.unich.scalafix.utils.Relation.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scalafix_2.12 Show documentation
Show all versions of scalafix_2.12 Show documentation
A Scala library for solving fixpoint equations
The newest version!
/**
* Copyright 2016 Gianluca Amato
*
* This file is part of ScalaFix.
* ScalaFix is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ScalaFix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of a
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ScalaFix. If not, see .
*/
package it.unich.scalafix.utils
import scala.collection.mutable
/**
* This trait represents an arbitrary mathematical relation over values of type `A`.
* It extends `A => collection.Set[A]` and the apply method is guaranteed to return a set (eventually empty)
* for each element of type `A`.
*
* @tparam A the domain of the relation.
*/
trait Relation[A] extends (A => collection.Set[A]) {
import Relation._
/**
* Returns a new relation where each element is in relation with itself.
*/
def withDiagonal: Relation[A] = new InfluenceWithDiagonal(this)
}
/**
* The `Relation` object contains factory methods and concrete implementations.
*/
object Relation {
private class InfluenceWithDiagonal[A](r: Relation[A]) extends Relation[A] {
def apply(x: A): collection.Set[A] = r(x) + x
override def withDiagonal: Relation[A] = this
}
private class InfluenceRelationFromFunction[A](f: A => collection.Set[A]) extends Relation[A] {
def apply(x: A): collection.Set[A] = f(x)
}
private class InfluenceRelationFromHash[A](hash: collection.Map[A, collection.Set[A]]) extends Relation[A] {
def apply(x: A): collection.Set[A] = hash.getOrElse(x, Set.empty[A])
}
/**
* Returns an influence relation given a function `A => Set[A]`. To respect the contract of a `Relation`, the map
* `f` should return a set for every possible value of `A`-
*/
def apply[A](f: A => Set[A]): Relation[A] = new InfluenceRelationFromFunction(f)
/**
* Returns an influence relation given a map `hash`. For elements which are not in the keyset of `hash`,
* it returns the empty set.
*/
def apply[A](hash: collection.Map[A, Set[A]]): Relation[A] = new InfluenceRelationFromHash(hash)
/**
* Returns an relation given a traversable collection of pairs `(u -> v)`, each pair meaning that `u`
* relates to `v`. When iterating over the image of `u`, elements are guaranteed to be returned in the
* order in which they appear in graph.
*/
def apply[A](graph: Seq[(A, A)]): Relation[A] = {
val hash: mutable.MultiMap[A, A] = new mutable.HashMap[A, mutable.Set[A]] with mutable.MultiMap[A, A] {
override def makeSet = new mutable.LinkedHashSet[A]
}
for ((u, v) <- graph) hash.addBinding(u, v)
new InfluenceRelationFromHash[A](hash)
}
}