All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spire.laws.VectorSpaceLaws.scala Maven / Gradle / Ivy

There is a newer version: 0.10.1
Show newest version
package spire.laws

import spire.algebra._
import spire.implicits._

import org.typelevel.discipline.{Laws, Predicate}

import org.scalacheck.{Arbitrary, Prop}
import org.scalacheck.Prop._

object VectorSpaceLaws {
  def apply[V: Eq: Arbitrary, A: Eq: Arbitrary: Predicate] = new VectorSpaceLaws[V, A] {
    val scalarLaws = RingLaws[A]
    val vectorLaws = GroupLaws[V]
  }
}

trait VectorSpaceLaws[V, A] extends Laws {

  implicit def scalar(implicit V: Module[V, A]): Rng[A] = V.scalar

  val scalarLaws: RingLaws[A]
  val vectorLaws: GroupLaws[V]

  import scalarLaws.{ Equ => EqA, Arb => ArA }
  import vectorLaws.{ Equ => EqV, Arb => ArV }


  def module(implicit V: Module[V, A]) = new SpaceProperties(
    name = "module",
    sl = _.rng(V.scalar),
    vl = _.abGroup(V.additive),
    parents = Seq.empty,

    "associative scalar" → forAll { (r: A, s: A, v: V) =>
      // TODO compiler crash if variable 'w' is replaced by its value
      val w = r *: s *: v
      w === ((r * s) *: v)
    },
    "scalar distributes over vector" → forAll((r: A, v: V, w: V) =>
      (r *: (v + w)) === ((r *: v) + (r *: w))
    ),
    "vector distributes over scalar" → forAll((r: A, s: A, v: V) =>
      ((r + s) *: v) === ((r *: v) + (s *: v))
    )/*,
    "scalar identity is identity" → forAll((v: V) =>
      (V.scalar.one *: v) === v
    )*/
  )

  def vectorSpace(implicit V: VectorSpace[V, A]) = new SpaceProperties(
    name = "vector space",
    sl = _.field(V.scalar),
    vl = _.abGroup(V.additive),
    parents = Seq(module)
  )

  def metricSpace(implicit V: MetricSpace[V, A], o: Order[A], A: Rng[A]) = new SpaceProperties(
    name = "metric space",
    sl = _.emptyRuleSet,
    vl = _.emptyRuleSet,
    parents = Seq.empty,
    "identity" → forAll((x: V, y: V) =>
      if (x === y) V.distance(x, y) === Rng[A].zero
      else V.distance(x, y) =!= Rng[A].zero
    ),
    "symmetric" → forAll((x: V, y: V) =>
      V.distance(x, y) === V.distance(y, x)
    ),
    "triangle inequality" → forAll((x: V, y: V, z: V) =>
      V.distance(x, z) <= (V.distance(x, y) + V.distance(y, z))
    )
  )

  def normedVectorSpace(implicit V: NormedVectorSpace[V, A], ev0: Order[A], ev1: Signed[A]) = new SpaceProperties(
    name = "normed vector space",
    sl = _.field(V.scalar),
    vl = _.abGroup(V.additive),
    parents = Seq(vectorSpace, metricSpace),

    "scalable" → forAll((a: A, v: V) =>
      a.abs * v.norm === (a.abs *: v).norm
    ),
    "only 1 zero" → forAll((v: V) => // This is covered by metricSpace...
      if (v === V.zero)
        v.norm === Rng[A].zero
      else
        v.norm > Rng[A].zero
    )
  )

  def linearity(f: V => A)(implicit V: Module[V, A]) = new SimpleRuleSet(
    name = "linearity",

    "homogeneity" → forAll((r: A, v: V) =>
      f(r *: v) === r * f(v)
    ),
    "additivity" → forAll((v: V, w: V) =>
      f(v + w) === f(v) + f(w)
    )
  )

  def innerProductSpace(implicit V: InnerProductSpace[V, A], A: Order[A], A0: Signed[A]) = SpaceProperties.fromParent(
    name = "inner-product space",
    parent = vectorSpace,

    "symmetry" → forAll((v: V, w: V) =>
      (v ⋅ w).abs === (w ⋅ v).abs
    ),
    "linearity of partial inner product" → forAll((w: V) =>
      // TODO this probably requires some thought -- should `linearity` be a full `RuleSet`?
      linearity(_ ⋅ w).all
    )
  )

  object SpaceProperties {
    def fromParent(name: String, parent: SpaceProperties, props: (String, Prop)*) =
      new SpaceProperties(name, parent.sl, parent.vl, Seq(parent), props: _*)
  }

  class SpaceProperties(
    val name: String,
    val sl: scalarLaws.type => scalarLaws.RuleSet,
    val vl: vectorLaws.type => vectorLaws.RuleSet,
    val parents: Seq[SpaceProperties],
    val props: (String, Prop)*
  ) extends RuleSet {
    val bases = Seq("scalar" → sl(scalarLaws), "vector" → vl(vectorLaws))
  }

}

// vim: expandtab:ts=2:sw=2




© 2015 - 2025 Weber Informatics LLC | Privacy Policy