# Buggy code
def train(self):
    """Runs one logical iteration of training.

    Subclasses should override ``_train()`` instead to return results.
    This class automatically fills the following fields in the result:

        `done` (bool): training is terminated. Filled only if not provided.

        `time_this_iter_s` (float): Time in seconds this iteration
        took to run. This may be overriden in order to override the
        system-computed time difference.

        `time_total_s` (float): Accumulated time in seconds for this
        entire experiment.

        `experiment_id` (str): Unique string identifier
        for this experiment. This id is preserved
        across checkpoint / restore calls.

        `training_iteration` (int): The index of this
        training iteration, e.g. call to train().

        `pid` (str): The pid of the training process.

        `date` (str): A formatted date of when the result was processed.

        `timestamp` (str): A UNIX timestamp of when the result
        was processed.

        `hostname` (str): Hostname of the machine hosting the training
        process.

        `node_ip` (str): Node ip of the machine hosting the training
        process.

    Returns:
        A dict that describes training progress.
    """

    start = time.time()
    result = self._train()
    assert isinstance(result, dict), "_train() needs to return a dict."

    result = result.copy()

    self._iteration += 1
    self._iterations_since_restore += 1

    if result.get(TIME_THIS_ITER_S) is not None:
        time_this_iter = result[TIME_THIS_ITER_S]
    else:
        time_this_iter = time.time() - start
    self._time_total += time_this_iter
    self._time_since_restore += time_this_iter

    result.setdefault(DONE, False)

    # self._timesteps_total should only be tracked if increments provided
    if result.get(TIMESTEPS_THIS_ITER):
        if self._timesteps_total is None:
            self._timesteps_total = 0
        self._timesteps_total += result[TIMESTEPS_THIS_ITER]
        self._timesteps_since_restore += result[TIMESTEPS_THIS_ITER]

    # self._timesteps_total should only be tracked if increments provided
    if result.get(EPISODES_THIS_ITER):
        if self._episodes_total is None:
            self._episodes_total = 0
        self._episodes_total += result[EPISODES_THIS_ITER]

    # self._timesteps_total should not override user-provided total
    result.setdefault(TIMESTEPS_TOTAL, self._timesteps_total)
    result.setdefault(EPISODES_TOTAL, self._episodes_total)

    # Provides auto-filled neg_mean_loss for avoiding regressions
    if result.get("mean_loss"):
        result.setdefault("neg_mean_loss", -result["mean_loss"])

    now = datetime.today()
    result.update(
        experiment_id=self._experiment_id,
        date=now.strftime("%Y-%m-%d_%H-%M-%S"),
        timestamp=int(time.mktime(now.timetuple())),
        training_iteration=self._iteration,
        time_this_iter_s=time_this_iter,
        time_total_s=self._time_total,
        pid=os.getpid(),
        hostname=os.uname()[1],
        node_ip=self._local_ip,
        config=self.config,
        time_since_restore=self._time_since_restore,
        timesteps_since_restore=self._timesteps_since_restore,
        iterations_since_restore=self._iterations_since_restore,
    )

    self._result_logger.on_result(result)

    return result


# Traceback (TypeError)
Traceback (most recent call last):
File "/home/eric/Desktop/ray-private/python/ray/tune/trial_runner.py", line 242, in _process_events
if trial.should_stop(result):
File "/home/eric/Desktop/ray-private/python/ray/tune/trial.py", line 213, in should_stop
if result[criteria] >= stop_value:
TypeError: unorderable types: NoneType() >= int()
Worker ip unknown, skipping log sync for /home/eric/ray_results/test/IMPALA_cartpole_stateless_4_2018-10-14_00-11-54wk3lun7w
== Status ==
Using FIFO scheduling algorithm.
Resources requested: 0/4 CPUs, 0/0 GPUs
Result logdir: /home/eric/ray_results/test
ERROR trials:
- IMPALA_cartpole_stateless_1:	ERROR, 1 failures: /home/eric/ray_results/test/IMPALA_cartpole_stateless_1_2018-10-14_00-11-08bzsn9bjz/error_2018-10-14_00-11-23.txt
- IMPALA_cartpole_stateless_2:	ERROR, 1 failures: /home/eric/ray_results/test/IMPALA_cartpole_stateless_2_2018-10-14_00-11-23zv6jbrbr/error_2018-10-14_00-11-38.txt
- IMPALA_cartpole_stateless_3:	ERROR, 1 failures: /home/eric/ray_results/test/IMPALA_cartpole_stateless_3_2018-10-14_00-11-38p18gjmul/error_2018-10-14_00-11-54.txt
- IMPALA_cartpole_stateless_4:	ERROR, 1 failures: /home/eric/ray_results/test/IMPALA_cartpole_stateless_4_2018-10-14_00-11-54wk3lun7w/error_2018-10-14_00-12-09.txt
TERMINATED trials:
- IMPALA_cartpole_stateless_0:	TERMINATED [pid=19362], 173 s, 17 iter, 143900 ts, 221 rew

# Fixed code
def train(self):
    """Runs one logical iteration of training.

    Subclasses should override ``_train()`` instead to return results.
    This class automatically fills the following fields in the result:

        `done` (bool): training is terminated. Filled only if not provided.

        `time_this_iter_s` (float): Time in seconds this iteration
        took to run. This may be overriden in order to override the
        system-computed time difference.

        `time_total_s` (float): Accumulated time in seconds for this
        entire experiment.

        `experiment_id` (str): Unique string identifier
        for this experiment. This id is preserved
        across checkpoint / restore calls.

        `training_iteration` (int): The index of this
        training iteration, e.g. call to train().

        `pid` (str): The pid of the training process.

        `date` (str): A formatted date of when the result was processed.

        `timestamp` (str): A UNIX timestamp of when the result
        was processed.

        `hostname` (str): Hostname of the machine hosting the training
        process.

        `node_ip` (str): Node ip of the machine hosting the training
        process.

    Returns:
        A dict that describes training progress.
    """

    start = time.time()
    result = self._train()
    assert isinstance(result, dict), "_train() needs to return a dict."

    result = result.copy()

    self._iteration += 1
    self._iterations_since_restore += 1

    if result.get(TIME_THIS_ITER_S) is not None:
        time_this_iter = result[TIME_THIS_ITER_S]
    else:
        time_this_iter = time.time() - start
    self._time_total += time_this_iter
    self._time_since_restore += time_this_iter

    result.setdefault(DONE, False)

    # self._timesteps_total should only be tracked if increments provided
    if result.get(TIMESTEPS_THIS_ITER) is not None:
        if self._timesteps_total is None:
            self._timesteps_total = 0
        self._timesteps_total += result[TIMESTEPS_THIS_ITER]
        self._timesteps_since_restore += result[TIMESTEPS_THIS_ITER]

    # self._episodes_total should only be tracked if increments provided
    if result.get(EPISODES_THIS_ITER) is not None:
        if self._episodes_total is None:
            self._episodes_total = 0
        self._episodes_total += result[EPISODES_THIS_ITER]

    # self._timesteps_total should not override user-provided total
    result.setdefault(TIMESTEPS_TOTAL, self._timesteps_total)
    result.setdefault(EPISODES_TOTAL, self._episodes_total)

    # Provides auto-filled neg_mean_loss for avoiding regressions
    if result.get("mean_loss"):
        result.setdefault("neg_mean_loss", -result["mean_loss"])

    now = datetime.today()
    result.update(
        experiment_id=self._experiment_id,
        date=now.strftime("%Y-%m-%d_%H-%M-%S"),
        timestamp=int(time.mktime(now.timetuple())),
        training_iteration=self._iteration,
        time_this_iter_s=time_this_iter,
        time_total_s=self._time_total,
        pid=os.getpid(),
        hostname=os.uname()[1],
        node_ip=self._local_ip,
        config=self.config,
        time_since_restore=self._time_since_restore,
        timesteps_since_restore=self._timesteps_since_restore,
        iterations_since_restore=self._iterations_since_restore,
    )

    self._result_logger.on_result(result)

    return result