Почему мелкая копия необходима для правильного обновления моего словаря значений?

Я работаю над классом Agent в Python 2.7.11, который использует Марковский процесс принятия решений (MDP) для поиска оптимальной политики π в GridWorld . Я выполняю базовую итерацию значений для 100 итераций всех состояний GridWorld используя следующее уравнение Беллмана:

введите описание изображения здесь

  • T (s, a, s ') – вероятностная функция успешного перехода к состоянию преемника s' из текущего состояния s , предпринимая действие a .
  • R (s, a, s ') – вознаграждение за переход от s к s' .
  • γ (гамма) – коэффициент дисконтирования, где 0 & leq; γ & leq; 1 .
  • V k (s ') является рекурсивным вызовом для повторения вычисления после достижения s' .
  • V k + 1 (s) является репрезентативным, как после того, как произошло достаточно k итераций, значение итерации V k будет сходиться и стать эквивалентным V k + 1

Это уравнение получается из принятия максимума функции значения Q , что я использую в своей программе:

введите описание изображения здесь

При создании моего Agent он передается MDP, который представляет собой абстрактный класс, содержащий следующие методы:

 # Returns all states in the GridWorld def getStates() # Returns all legal actions the agent can take given the current state def getPossibleActions(state) # Returns all possible successor states to transition to from the current state # given an action, and the probability of reaching each with that action def getTransitionStatesAndProbs(state, action) # Returns the reward of going from the current state to the successor state def getReward(state, action, nextState) 

Мой Agent также получает коэффициент дисконтирования и ряд итераций. Я также использую dictionary для отслеживания моих ценностей. Вот мой код:

 class IterationAgent: def __init__(self, mdp, discount = 0.9, iterations = 100): self.mdp = mdp self.discount = discount self.iterations = iterations self.values = util.Counter() # A Counter is a dictionary with default 0 for transition in range(0, self.iterations, 1): states = self.mdp.getStates() valuesCopy = self.values.copy() for state in states: legalMoves = self.mdp.getPossibleActions(state) convergedValue = 0 for move in legalMoves: value = self.computeQValueFromValues(state, move) if convergedValue <= value or convergedValue == 0: convergedValue = value valuesCopy.update({state: convergedValue}) self.values = valuesCopy def computeQValueFromValues(self, state, action): successors = self.mdp.getTransitionStatesAndProbs(state, action) reward = self.mdp.getReward(state, action, successors) qValue = 0 for successor, probability in successors: # The Q value equation: Q*(a,s) = T(s,a,s')[R(s,a,s') + gamma(V*(s'))] qValue += probability * (reward + (self.discount * self.values[successor])) return qValue 

Эта реализация верна, хотя я не уверен, почему мне нужны valuesCopy чтобы выполнить успешное обновление в моем словаре self.values . Я пробовал следующее опустить копирование, но оно не работает, поскольку оно возвращает несколько неправильные значения:

 for i in range(0, self.iterations, 1): states = self.mdp.getStates() for state in states: legalMoves = self.mdp.getPossibleActions(state) convergedValue = 0 for move in legalMoves: value = self.computeQValueFromValues(state, move) if convergedValue <= value or convergedValue == 0: convergedValue = value self.values.update({state: convergedValue}) 

Мой вопрос заключается в том, почему включает в себя копию моего слова self.values необходимого для правильного обновления моих значений, когда valuesCopy = self.values.copy() делает копию словаря в любом случае на каждой итерации? Не следует ли обновлять значения в исходном результате в том же обновлении?

    Существует алгоритмическая разница в наличии или отсутствии копии:

     # You update your copy here, so the original will be used unchanged, which is not the # case if you don't have the copy valuesCopy.update({state: convergedValue}) # If you have the copy, you'll be using the old value stored in self.value here, # not the updated one qValue += probability * (reward + (self.discount * self.values[successor]))