scala trait成员和派生变量

时间:2015-08-18 10:46:26

标签: scala inheritance traits

我正在尝试用scala编写一个简单的爬山算法。

我有StateHillClimbing这些特征。 当我将它们应用于Graph问题时,我将它们定义为具体类。

GraphHillClimbing我收到两个错误。这是因为我使用GraphState而不是State(注意GraphState也是State)。

我该如何解决这个问题?

trait State {

  val loc = 0

  def neighbours: List[State]

  def get_loc():Int = return loc

}


class GraphState(loc:Int, g: Map[Int, List[Int]]) extends State {

  def neighbours():List[GraphState] =
  {
    def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
    {
      if(l.isEmpty) acc
      else {
        val new_neig = new GraphState(l.head, g)
        neighboursAcc(l.tail, List(new_neig) ++ acc, g)
      }
    }
    neighboursAcc(g(loc), List(), g)
  }

}


trait HillClimbing {

  val max_iteration = 4
  val start:State

  def cost(state:State):Double

  private def argmin(costs:List[Double]):Int = {
    val best = costs.min
    costs.indexOf(best)
  }

  private def next_best(states:List[State]):State = {
    val costs = states map(x => cost(x))
    val pos = argmin(costs)
    states(pos)
  }

  def minimize():State = {
    def minimizeAcc(iteration:Int, state:State):State =
    {
      if(iteration > max_iteration) state
      else {
        val neigs = state.neighbours
        val next_state = next_best(neigs)
        minimizeAcc(iteration+1, next_state)
      }
    }
    minimizeAcc(0, start)
  }

}


class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {

   // ERROR 1 = start was State and now it is GraphState
   // ERROR 2 = cost should take a State

   def cost(current_state:GraphState):Double = {
     val distance = goal.get_loc() - current_state.get_loc()
     if(distance > 0 ) distance
     else -distance
   }


}



object RunHillClimbing {
  def main(args: Array[String]) {


    val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))

    val start = new GraphState(1, G)
    val goal = new GraphState(6, G)

    val hc = new GraphHillClimbing(start, goal)
    print(hc.minimize())

  }
}

2 个答案:

答案 0 :(得分:3)

我认为这可以使用类型为bounds的类型参数来解决。

同样在GraphHillClimbing的构造函数中,您应该使用val来指示参数start是抽象start的具体实现。

trait State[+Self] {
  Self =>
  def loc:Int

  def neighbours: List[Self]

  def get_loc():Int = return loc
}

class GraphState(val loc:Int, g: Map[Int, List[Int]]) extends State[GraphState] {

  def neighbours():List[GraphState] =
  {
    def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
    {
      if(l.isEmpty) acc
      else {
        val new_neig = new GraphState(l.head, g)
        neighboursAcc(l.tail, List(new_neig) ++ acc, g)
      }
    }
    neighboursAcc(g(loc), List(), g)
  }
}

trait HillClimbing[T<:State[T]] {
  val max_iteration = 4
  val start:T

  def cost(state:T):Double

  private def argmin(costs:List[Double]):Int = {
    val best = costs.min
    costs.indexOf(best)
  }

  private def next_best(states:List[T]):T = {
    val costs = states map(x => cost(x))
    val pos = argmin(costs)
    states(pos)
  }

  def minimize():T = {
    def minimizeAcc(iteration:Int, state:T):T =
    {
      if(iteration > max_iteration) state
      else {
        val neigs = state.neighbours
        val next_state = next_best(neigs)
        minimizeAcc(iteration+1, next_state)
      }
    }
    minimizeAcc(0, start)
  }
}

class GraphHillClimbing(val start:GraphState, goal:GraphState) extends HillClimbing[GraphState] {

  def cost(current_state:GraphState):Double = {
    val distance = goal.get_loc() - current_state.get_loc()
    if(distance > 0 ) distance
    else -distance
  }
}

object RunHillClimbing {
  def main(args: Array[String]) {

    val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))

    val start = new GraphState(1, G)
    val goal = new GraphState(6, G)

    val hc = new GraphHillClimbing(start, goal)
    print(hc.minimize())
  }
}

答案 1 :(得分:0)

我得到了什么:

error: class GraphHillClimbing needs to be abstract, since:
it has 2 unimplemented members.
/** As seen from class GraphHillClimbing, the missing signatures are as follows.
*  For convenience, these are usable as stub implementations.
*/
  def cost(state: this.State): Double = ???
  val start: this.State = ???

class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {
      ^

使用GraphState替换类中的State,因为继承 要求您必须处理State而不是GraphState

然后替换

 val loc = 0

 def loc = 0

所以你可以在GraphState中覆盖它。