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

scalax.collection.edge.Base.scala Maven / Gradle / Ivy

The newest version!
package scalax.collection.edge

import language.implicitConversions
import scala.reflect.ClassTag

import scalax.collection.GraphEdge._, scalax.collection.GraphPredef._
import scalax.collection.{Graph, GraphBase}

/** Base traits for weighted edges.
  *
  * @author Peter Empen
  */
object WBase {
  trait WEdge[+N] { this: EdgeLike[N] =>
    override protected def attributesToString = WEdge.wPrefix + weight.toString
  }
  object WEdge {
    val wPrefix = " %"
  }
  type WHyperEdgeBound[+N] = EdgeLikeIn[N] with HyperEdge[N] with WEdge[N] with Serializable

  /** Everything common to weighted hyperedge companion objects. */
  trait WHyperEdgeCompanion[E[+X] <: WHyperEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N](node_1: N, node_2: N, nodes: N*)(weight: Double)(implicit kind: CollectionKind = Bag) =
      newEdge[N](NodeProduct(node_1, node_2, nodes: _*), weight)
    @inline final def apply[N](nodes: Iterable[N])(weight: Double)(implicit kind: CollectionKind) =
      newEdge[N](NodeProduct(nodes), weight)
    @inline final protected[collection] def from[N](nodes: Product)(weight: Double)(implicit kind: CollectionKind) =
      newEdge[N](nodes, weight)
    protected def newEdge[N](nodes: Product, weight: Double)(implicit kind: CollectionKind): E[N] with EdgeCopy[E]
    @inline final def unapply[N](e: E[N]): Option[(Iterable[N], Double)] = Some((e.sources, e.weight))
  }
  type WEdgeBound[+N] = WHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to weighted edge companion objects. */
  trait WEdgeCompanion[E[+X] <: WEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N](node_1: N, node_2: N)(weight: Double) =
      newEdge[N](NodeProduct(node_1, node_2), weight)
    @inline final def apply[N](nodes: (N, N))(weight: Double) =
      newEdge[N](nodes, weight)
    @inline final protected[collection] def from[N](nodes: Product)(weight: Double) =
      newEdge[N](nodes, weight)
    protected def newEdge[N](nodes: Product, weight: Double): E[N] with EdgeCopy[E]
    @inline final def unapply[N](e: E[N]): Option[(N, N, Double)] = Some(e._1, e._2, e.weight)
  }
}

/** Base traits for key-weighted edges. */
object WkBase {
  import WBase._
  trait WkEdge[+N] extends WEdge[N] with Keyed {
    this: EdgeLike[N] with Eq =>
    override protected def equals(other: EdgeLike[_]) =
      this.weight == other.weight && (other match {
        case wkEdge: WkEdge[_] => baseEquals(wkEdge)
        case _                 => false
      })
    override def hashCode = baseHashCode ^ weight.##
  }
  type WkHyperEdgeBound[+N] = WHyperEdgeBound[N] with WkEdge[N]

  /** Everything common to key-weighted hyperedge companion objects. */
  trait WkHyperEdgeCompanion[E[+X] <: WkHyperEdgeBound[X]] extends WHyperEdgeCompanion[E]
  type WkEdgeBound[+N] = WkHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to key-weighted edge companion objects. */
  trait WkEdgeCompanion[E[+X] <: WkEdgeBound[X]] extends WEdgeCompanion[E]
}

/** Base traits for labeled edges. */
object LBase {
  trait LEdge[+N] { this: EdgeLike[N] =>
    type L1
    override def label: L1                    = throw new IllegalArgumentException
    override protected def attributesToString = LEdge.lPrefix + label
  }
  object LEdge {
    val lPrefix  = " '"
    val lkPrefix = " `"
  }
  type LHyperEdgeBound[+N] = EdgeLikeIn[N] with HyperEdge[N] with LEdge[N] with Serializable

  /** Everything common to labeled hyperedge companion objects. */
  trait LHyperEdgeCompanion[E[+X] <: LHyperEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N, L](node_1: N, node_2: N, nodes: N*)(label: L)(implicit kind: CollectionKind = Bag) =
      newEdge[N, L](NodeProduct(node_1, node_2, nodes: _*), label)
    @inline final def apply[N, L](nodes: Iterable[N])(label: L)(implicit kind: CollectionKind) =
      newEdge[N, L](NodeProduct(nodes), label)
    @inline final protected[collection] def from[N, L](nodes: Product)(label: L)(implicit kind: CollectionKind) =
      newEdge[N, L](nodes, label)
    protected def newEdge[N, L](nodes: Product, label_1: L)(
        implicit kind: CollectionKind): E[N] with EdgeCopy[E] { type L1 = L }
    @inline final def unapply[N](e: E[N]): Option[(Iterable[N], E[N]#L1)] =
      Some((e.sources, e.label))
  }
//  type LEdgeBound[N, +E[+X] <: EdgeLikeIn[X]] = LHyperEdgeBound[N, E] with UnDiEdge[N]
  type LEdgeBound[+N] = LHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to predefined edge labeled edge companion objects. */
  trait LEdgeCompanion[E[+X] <: LEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N, L](node_1: N, node_2: N)(label: L) =
      newEdge[N, L](NodeProduct(node_1, node_2), label)
    @inline final def apply[N, L](nodes: Tuple2[N, N])(label: L) =
      newEdge[N, L](nodes, label)
    @inline final protected[collection] def from[N, L](nodes: Product)(label: L) =
      newEdge[N, L](nodes, label)
    protected def newEdge[N, L](nodes: Product, label_1: L): E[N] with EdgeCopy[E] { type L1 = L }
    @inline final def unapply[N](e: E[N]): Option[(N, N, E[N]#L1)] =
      Some((e._1, e._2, e.label))
  }

  /** Implicit conversions from an outer labeled edge to its label.
    *
    * @tparam UL type of the user label.
    */
  abstract class OuterLEdgeImplicits[UL: ClassTag] {

    /** Lets implicitly convert a labeled outer edge to its label:
      {{{
      case class MyLabel(val i: Int)
      val eOuter = LUnDiEdge(1,3)(MyLabel(4))

      object MyLabelConversion extends OuterLEdgeImplicits[MyLabel]
      import MyLabelConversion._
      val four = eOuter.i
      }}}
      */
    implicit def outerLEdge2UserLabel[N](edge: LEdge[N] { type L1 = UL }): UL = edge.label

    /** Lets implicitly convert a label to its user type:
      {{{
      case class MyLabel(val i: Int)
      val eOuter = LUnDiEdge(1,3)(MyLabel(4))

      object MyLabelConversion extends OuterLEdgeImplicits[MyLabel]
      import MyLabelConversion._
      val label: MyLabel = eOuter.label
      }}}
      As this conversion is not type safe, the user has to ensure that `label`
      is of the type `UL`.
      */
    implicit def toUserLabel[N, E[+X] <: LEdge[X]](label: E[N]#L1): UL =
      try label.asInstanceOf[UL]
      catch {
        case e: ClassCastException => handle(label)
      }

    protected def handle(label: Any) = throw new IllegalArgumentException(
      s"Expected label type: ${implicitly[ClassTag[UL]].runtimeClass.getName}, found: ${label match {
        case r: AnyRef => r.getClass.getName
        case a         => a.toString
      }}.")
  }

  /** Implicit conversions from an inner or outer labeled edge to its label.
    *  In case of inner edges, this trait works for [[scalax.collection.Graph]] only.
    *  For other graph types see [[scalax.collection.edge.LBase.TypedLEdgeImplicits]].
    *
    * @tparam UL type of the user label.
    */
  abstract class LEdgeImplicits[UL: ClassTag] extends OuterLEdgeImplicits[UL] {

    /** Lets implicitly convert a labeled inner edge to its label:
      {{{
      case class MyLabel(val i: Int)
      val g = Graph(LUnDiEdge(1,3)(MyLabel(4)))
      val eInner = g.edges.head

      object MyLabelConversion extends LEdgeImplicits[MyLabel]
      import MyLabelConversion._
      val four_2 = eInner.i
      }}}
      As this conversion is not type safe, the user has to ensure that `innerEdge`
      is of appropriate type.
      */
    implicit def innerEdge2UserLabel[N, E[+X] <: EdgeLikeIn[X]](innerEdge: Graph[N, E]#EdgeT): UL =
      try innerEdge.edge.label.asInstanceOf[UL]
      catch {
        case e: ClassCastException => handle(innerEdge)
      }
  }

  /** Implicit conversions from an inner or outer labeled edge to its label
    *  for any graph type.
    *
    * @tparam G kind of type of graph.
    * @tparam UL type of the user label.
    */
  abstract class TypedLEdgeImplicits[G[N, E[+X] <: EdgeLikeIn[X]] <: GraphBase[N, E], UL: ClassTag]
      extends OuterLEdgeImplicits[UL] {

    /** Lets implicitly convert a labeled inner edge to its label:
      {{{
      import scalax.collection.mutable.{Graph => MGraph}

      case class MyLabel(val i: Int)
      val g = MGraph(LUnDiEdge(1,3)(MyLabel(4)))
      val eInner = g.edges.head

      object MyLabelConversion extends TypedLEdgeImplicits[MGraph, MyLabel]
      import MyLabelConversion._
      val four_2 = eInner.i
      }}}
      As this conversion is not type safe, the user has to ensure that `innerEdge`
      is of appropriate type.
      */
    implicit def innerEdge2UserLabel[N, E[+X] <: EdgeLikeIn[X]](innerEdge: G[N, E]#EdgeT): UL =
      try innerEdge.edge.label.asInstanceOf[UL]
      catch {
        case e: ClassCastException => handle(innerEdge)
      }
  }
}

/** Base traits for key-labeled edges. */
object LkBase {
  import LBase._

  /** Everything common to all predefined labeled edge classes with a label being a key attribute.
    *  Such labeled and keyed edge classes are named `LkEdge` by convention.
    */
  trait LkEdge[+N] extends LEdge[N] with Keyed {
    this: EdgeLike[N] with Eq =>
    override protected def equals(other: EdgeLike[_]) = other match {
      case that: LkEdge[_] =>
        this.label == that.label &&
          baseEquals(that)
      case _ => false
    }
    override def hashCode = baseHashCode ^ label.##
  }
  type LkHyperEdgeBound[+N] = LHyperEdgeBound[N] with LkEdge[N]

  /** Everything common to key-weighted hyperedge companion objects. */
  trait LkHyperEdgeCompanion[E[+X] <: LkHyperEdgeBound[X]] extends LHyperEdgeCompanion[E]
  type LkEdgeBound[+N] = LkHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to key-weighted edge companion objects. */
  trait LkEdgeCompanion[E[+X] <: EdgeLikeIn[X] with LkEdgeBound[X]] extends LEdgeCompanion[E]
}

/** Base traits for weighted and labeled edges. */
object WLBase {
  import WBase._, LBase._

  /** Everything common to predefined weighted and labeled edge classes.
    *  Such edge classes are prefixed with  `WL` by convention.
    */
  trait WLEdge[+N] extends WEdge[N] with LEdge[N] { this: EdgeLike[N] =>
    override protected def attributesToString = WEdge.wPrefix + weight.toString +
      LEdge.lPrefix + label.toString
  }
  type WLHyperEdgeBound[+N] = EdgeLikeIn[N] with HyperEdge[N] with WLEdge[N] with Serializable

  /** Everything common to predefined weighted and labeled hyperedge companion objects. */
  trait WLHyperEdgeCompanion[E[+X] <: WLHyperEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N, L](node_1: N, node_2: N, nodes: N*)(weight: Double, label: L)(
        implicit kind: CollectionKind = Bag) =
      newEdge[N, L](NodeProduct(node_1, node_2, nodes: _*), weight, label)
    @inline final def apply[N, L](nodes: Iterable[N])(weight: Double, label: L)(implicit kind: CollectionKind) =
      newEdge[N, L](NodeProduct(nodes), weight, label)
    @inline final protected[collection] def from[N, L](nodes: Product)(weight: Double, label: L)(
        implicit kind: CollectionKind) =
      newEdge[N, L](nodes, weight, label)
    protected def newEdge[N, L](nodes: Product, weight: Double, label_1: L)(
        implicit kind: CollectionKind): E[N] with EdgeCopy[E]
    @inline final def unapply[N](e: E[N]): Option[(Iterable[N], Double, E[N]#L1)] =
      Some((e.sources, e.weight, e.label))
  }
  type WLEdgeBound[+N] = WLHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to predefined weighted and labeled edge companion objects. */
  trait WLEdgeCompanion[E[+X] <: WLEdgeBound[X]] extends EdgeCompanionBase[E] {
    @inline final def apply[N, L](node_1: N, node_2: N)(weight: Double, label: L) =
      newEdge[N, L](NodeProduct(node_1, node_2), weight, label)
    @inline final def apply[N, L](nodes: Tuple2[N, N])(weight: Double, label: L) =
      newEdge[N, L](nodes, weight, label)
    @inline final protected[collection] def from[N, L](nodes: Product)(weight: Double, label: L) =
      newEdge[N, L](nodes, weight, label)
    protected def newEdge[N, L](nodes: Product, weight: Double, label_1: L): E[N] with EdgeCopy[E]
    @inline final def unapply[N](e: E[N]): Option[(N, N, Double, E[N]#L1)] =
      Some((e._1, e._2, e.weight, e.label))
  }
}

/** Base traits for key-weighted and labeled edges. */
object WkLBase {
  import WkBase._, WLBase._
  type WkLHyperEdgeBound[+N] = WLHyperEdgeBound[N] with WLEdge[N] with WkEdge[N]

  /** Everything common to key-weighted, labeled hyperedge companion objects. */
  trait WkLHyperEdgeCompanion[E[+X] <: WkLHyperEdgeBound[X]] extends WLHyperEdgeCompanion[E]
  type WkLEdgeBound[+N] = WkLHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to key-weighted, labeled edge companion objects. */
  trait WkLEdgeCompanion[E[+X] <: WkLEdgeBound[X]] extends WLEdgeCompanion[E]
}

/** Base traits for weighted and key-labeled edges. */
object WLkBase {
  import WBase._, LBase._, LkBase._, WLBase._
  trait WLkEdge[+N] extends WEdge[N] with LkEdge[N] { this: EdgeLike[N] with Eq =>
    override protected def attributesToString = WEdge.wPrefix + weight.toString +
      LEdge.lkPrefix + label.toString
  }
  type WLkHyperEdgeBound[+N] = WLHyperEdgeBound[N] with WLkEdge[N]

  /** Everything common to weighted, key-labeled hyperedge companion objects. */
  trait WLkHyperEdgeCompanion[E[+X] <: WLkHyperEdgeBound[X]] extends WLHyperEdgeCompanion[E]
  type WLkEdgeBound[+N] = WLkHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to weighted, key-labeled edge companion objects. */
  trait WLkEdgeCompanion[E[+X] <: WLkEdgeBound[X]] extends WLEdgeCompanion[E]
}

/** Base traits for key-weighted and key-labeled edges. */
object WkLkBase {
  import WLBase._
  trait WkLkEdge[+N] extends WLEdge[N] { this: EdgeLike[N] with Eq =>
    override protected def equals(other: EdgeLike[_]) = other match {
      case that: WkLkEdge[_] =>
        this.weight == that.weight &&
          this.label == that.label &&
          baseEquals(that)
      case _ => false
    }
    override def hashCode =
      baseHashCode ^ (weight.hashCode) ^ label.hashCode
  }
  type WkLkHyperEdgeBound[+N] = WLHyperEdgeBound[N] with WkLkEdge[N]

  /** Everything common to weighted, key-labeled hyperedge companion objects. */
  trait WkLkHyperEdgeCompanion[E[+X] <: EdgeLikeIn[X] with WkLkHyperEdgeBound[X]] extends WLHyperEdgeCompanion[E]
  type WkLkEdgeBound[+N] = WkLkHyperEdgeBound[N] with UnDiEdge[N]

  /** Everything common to weighted, key-labeled edge companion objects. */
  trait WkLkEdgeCompanion[E[+X] <: EdgeLikeIn[X] with WkLkEdgeBound[X]] extends WLEdgeCompanion[E]
}

/** Base traits for custom edges - hence the `C` prefix. Note that custom edges need only
  *  to mix in `CBase.Attributes` when importing by `fromJson`.
  */
object CBase {

  /** To be mixed in by the custom edge class. */
  trait Attributes[+N] { this: EdgeLike[N] =>

    /** To be set to `.P`. */
    type P <: Product

    /** Must return an instance of `Tuple` with `n` being the number of
      *  custom attributes. Custom attributes are defined by the constructor parameters
      *  excluding those representing nodes. */
    def attributes: P
  }
  type CHyperEdgeBound[+N] = EdgeLikeIn[N] with HyperEdge[N] with Attributes[N] with Serializable
  trait CEdgeCompanionBase[E[+X] <: EdgeLikeIn[X] with CHyperEdgeBound[X]] extends EdgeCompanionBase[E] {
    protected[collection] type P <: Product
  }

  /** To be mixed in by custom hyperedge companion objects. */
  trait CHyperEdgeCompanion[E[+X] <: CHyperEdgeBound[X]] extends CEdgeCompanionBase[E] {
    @inline final def apply[N](node_1: N, node_2: N, nodes: N*)(attr: P)(implicit kind: CollectionKind = Bag) =
      newEdge[N](NodeProduct(node_1, node_2, nodes: _*), attr)
    @inline final def apply[N](nodes: Iterable[N], attr: P)(implicit kind: CollectionKind) =
      newEdge[N](NodeProduct(nodes), attr)
    @inline final protected[collection] def from[N](nodes: Product, attr: P)(implicit kind: CollectionKind) =
      newEdge[N](nodes, attr)

    /** Must return an instance of the custom edge which is achieved by projecting the elements
      *  of `attr` and passing them as single arguments to the custom edge constructor. */
    protected def newEdge[N](nodes: Product, attr: P)(implicit kind: CollectionKind = Bag): E[N] with EdgeCopy[E]
  }
  type CEdgeBound[+N] = CHyperEdgeBound[N] with UnDiEdge[N]

  /** To be mixed in by custom edge companion objects. */
  trait CEdgeCompanion[E[+X] <: CEdgeBound[X]] extends CEdgeCompanionBase[E] {
    @inline final def apply[N](node_1: N, node_2: N, attr: P) =
      newEdge[N](NodeProduct(node_1, node_2), attr)
    @inline final def apply[N](nodes: Tuple2[N, N], attr: P) =
      newEdge[N](nodes, attr)
    @inline final protected[collection] def from[N](nodes: Product, attr: P) =
      newEdge[N](nodes, attr)

    /** Must return an instance of the custom edge which is achieved by projecting the elements
      *  of `attr` and passing them as single arguments to the custom edge constructor. */
    protected def newEdge[N](nodes: Product, attr: P): E[N] with EdgeCopy[E]
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy