def early_stop(patience, max_factor, vae_loss_val, em_loss_val):
    """
    Manual implementation of https://keras.io/api/callbacks/early_stopping/.
    :param patience: max number of epochs loss has not decreased
    :param max_factor: max_factor * current loss is the max acceptable loss
    :param vae_loss_val: list of vae validation losses
    :param em_loss_val: list of emulator validation losses
    :return: boolean, True (keep going) or False (stop early)
    """
    if not len(em_loss_val) > patience:  # there is not enough training to compare
        return True

    if vae_loss_val is not None:
        vae_max_loss = vae_loss_val[-(1 + patience)] * max_factor  # the max acceptable loss
    else:
        vae_max_loss = None
    em_max_loss = em_loss_val[-(1 + patience)] * max_factor  # the max acceptable loss

    count = 0
    while count < patience:
        if em_loss_val[-(1 + count)] > em_max_loss:
            if vae_loss_val is None:
                count += 1
                continue
            elif vae_loss_val[-(1 + count)] > vae_max_loss:
                count += 1
                continue
            else:
                break
        else:
            break
    if count == patience:  # the last [patience] losses are all too large: stop training
        print("Early stopping!")
        return False  # keep_going = False, i.e. stop early
    else:
        return True