From a46a00512e9745e3fd328ceaa339c578e60c147d Mon Sep 17 00:00:00 2001 From: Norbert Kozlowski Date: Sun, 14 Oct 2018 11:19:20 +0200 Subject: [PATCH] PEP8 changes --- .editorconfig | 28 +++++ .travis.yml | 2 +- Makefile | 8 +- examples/checkerboard.py | 2 +- examples/handeye.py | 15 +-- examples/maze.py | 10 +- gym_checkerboard/__init__.py | 2 +- gym_checkerboard/checkerboard.py | 8 +- gym_checkerboard/checkerboard_simulator.py | 7 +- gym_handeye/__init__.py | 2 +- gym_handeye/handeye.py | 48 +++++--- gym_handeye/handeye_simulator.py | 43 ++++--- gym_handeye/tests/test_handeye.py | 2 +- gym_handeye/utils/utils.py | 8 +- gym_maze/__init__.py | 2 +- gym_maze/envs/MazeF3.py | 2 +- gym_maze/envs/abstract_maze.py | 4 +- gym_maze/maze.py | 2 +- gym_maze/utils/utils.py | 4 +- gym_multiplexer/__init__.py | 2 +- gym_multiplexer/boolean_multiplexer.py | 5 +- gym_multiplexer/multiplexer.py | 76 ++++++------ gym_multiplexer/real_multiplexer.py | 23 ++-- .../tests/test_boolean_multiplexer.py | 4 +- .../tests/test_real_multiplexer.py | 111 +++++++++--------- gym_multiplexer/tests/test_utils.py | 8 +- gym_multiplexer/utils/__init__.py | 2 +- requirements.txt | 4 +- setup.cfg | 6 + 29 files changed, 256 insertions(+), 184 deletions(-) create mode 100644 .editorconfig create mode 100644 setup.cfg diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..41bbf0c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,28 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 + +# 4 space indentation +[*.py] +indent_style = space +indent_size = 4 +max_line_length = 79 + +[*.maze] +insert_final_newline = false + +# Matches the exact files either package.json or .travis.yml +[*.yml] +indent_style = space +indent_size = 2 + +[Makefile] +indent_style = tab +indent_size = 8 diff --git a/.travis.yml b/.travis.yml index 72d18f6..5579347 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ python: script: - pip install -r requirements.txt - - pytest + - make test deploy: skip_cleanup: true diff --git a/Makefile b/Makefile index 554bc09..54c9d54 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,6 @@ -test: - pytest \ No newline at end of file +lint: + mypy . + +test: lint + py.test --pep8 -m pep8 + py.test \ No newline at end of file diff --git a/examples/checkerboard.py b/examples/checkerboard.py index 7ae821b..a52b535 100644 --- a/examples/checkerboard.py +++ b/examples/checkerboard.py @@ -19,4 +19,4 @@ state, reward, done, info = env.step(action) logging.info(f"\tObtained reward: {reward}, state: {state}") - logging.info("Finished") \ No newline at end of file + logging.info("Finished") diff --git a/examples/handeye.py b/examples/handeye.py index 612ca95..7e6d34d 100644 --- a/examples/handeye.py +++ b/examples/handeye.py @@ -1,5 +1,4 @@ import logging -from random import choice import gym @@ -11,22 +10,20 @@ if __name__ == '__main__': hand_eye = gym.make('HandEye3-v0') - possible_actions = list(range(6)) - for i_episode in range(1): observation = hand_eye.reset() for t in range(100): - logging.info("Time: [{}], observation: [{}]".format(t, observation)) + logging.info(f"Time: [{t}], observation: [{observation}]") - action = choice(possible_actions) + action = hand_eye.action_space.sample() - logging.info("\t\tExecuted action: [{}]".format(action)) + logging.info(f"\t\tExecuted action: [{action}]") observation, reward, done, info = hand_eye.step(action) if done: - logging.info("Episode finished after {} timesteps.".format(t + 1)) - logging.info("Last reward: {}".format(reward)) + logging.info(f"Episode finished after {t+1} timesteps.") + logging.info(f"Last reward: {reward}") break - logging.info("Finished") \ No newline at end of file + logging.info("Finished") diff --git a/examples/maze.py b/examples/maze.py index 0d9d24d..2e82fc4 100644 --- a/examples/maze.py +++ b/examples/maze.py @@ -1,5 +1,4 @@ import logging -from random import choice import gym @@ -11,23 +10,22 @@ if __name__ == '__main__': maze = gym.make('MazeF1-v0') - possible_actions = list(range(8)) transitions = maze.env.get_all_possible_transitions() for i_episode in range(1): observation = maze.reset() for t in range(100): - logging.info("Time: [{}], observation: [{}]".format(t, observation)) + logging.info(f"Time: [{t}], observation: [{observation}]") - action = choice(possible_actions) + action = maze.action_space.sample() logging.info("\t\tExecuted action: [{}]".format(action)) observation, reward, done, info = maze.step(action) if done: - logging.info("Episode finished after {} timesteps.".format(t + 1)) - logging.info("Last reward: {}".format(reward)) + logging.info(f"Episode finished after {t+1} timesteps.") + logging.info(f"Last reward: {reward}") break logging.info("Finished") diff --git a/gym_checkerboard/__init__.py b/gym_checkerboard/__init__.py index 7c79632..10dae72 100644 --- a/gym_checkerboard/__init__.py +++ b/gym_checkerboard/__init__.py @@ -31,4 +31,4 @@ entry_point='gym_checkerboard:Checkerboard', max_episode_steps=max_episode_steps, kwargs={'dim': 2, 'ndiv': 5} -) \ No newline at end of file +) diff --git a/gym_checkerboard/checkerboard.py b/gym_checkerboard/checkerboard.py index 61044b0..67d71a7 100644 --- a/gym_checkerboard/checkerboard.py +++ b/gym_checkerboard/checkerboard.py @@ -1,4 +1,5 @@ import logging +from typing import List import gym import numpy as np @@ -8,16 +9,17 @@ logger = logging.getLogger(__name__) + class Checkerboard(gym.Env): metadata = {'render.modes': ['human', 'ansi']} REWARD = 1 - def __init__(self, dim: int, ndiv: int): + def __init__(self, dim: int, ndiv: int) -> None: logger.debug("Initializing environment") self._dim = dim self._board = CheckerboardSimulator(dim, ndiv) - self._state = None + self._state: List = [] self._validation_bit = 0 self.action_space = Discrete(2) @@ -60,4 +62,4 @@ def _observation(self) -> list: @property def _true_color(self) -> int: - return self._board.get_color(*self._state) \ No newline at end of file + return self._board.get_color(*self._state) diff --git a/gym_checkerboard/checkerboard_simulator.py b/gym_checkerboard/checkerboard_simulator.py index d563f8c..7e69cdb 100644 --- a/gym_checkerboard/checkerboard_simulator.py +++ b/gym_checkerboard/checkerboard_simulator.py @@ -3,9 +3,10 @@ WHITE = 0 BLACK = 1 + class CheckerboardSimulator: - def __init__(self, dim: int, ndiv: int): + def __init__(self, dim: int, ndiv: int) -> None: """ :param n: dimensionality of solution space :param nd: division of each dimension, @@ -36,7 +37,3 @@ def get_color(self, *cords) -> int: def _get_index(self, val: float) -> int: y = np.linspace(0, 1, self.nd + 1) return np.where(y <= val)[0][-1] - - - - diff --git a/gym_handeye/__init__.py b/gym_handeye/__init__.py index d659559..a161600 100644 --- a/gym_handeye/__init__.py +++ b/gym_handeye/__init__.py @@ -58,4 +58,4 @@ entry_point='gym_handeye:HandEye', max_episode_steps=500, kwargs={'grid_size': 9, 'note_in_hand': True, 'test_only_changes': 0} -) \ No newline at end of file +) diff --git a/gym_handeye/handeye.py b/gym_handeye/handeye.py index f407b58..e83a349 100644 --- a/gym_handeye/handeye.py +++ b/gym_handeye/handeye.py @@ -5,7 +5,8 @@ from gym.spaces import Discrete import gym_handeye.utils.utils as utils -from gym_handeye.handeye_simulator import HandEyeSimulator, SURFACE, BLOCK, GRIPPER, ACTION_LOOKUP +from gym_handeye.handeye_simulator import HandEyeSimulator, SURFACE, BLOCK, \ + GRIPPER, ACTION_LOOKUP class HandEye(gym.Env): @@ -15,10 +16,12 @@ def __init__(self, grid_size, note_in_hand, test_only_changes=0): """ :param grid_size: specifies the size of the monitored plain - :param note_in_hand: specifies if the tacticle sensor should switch to '2' if the block is held by the gripper + :param note_in_hand: specifies if the tacticle sensor should + switch to '2' if the block is held by the gripper (if False, then goes back to '0') - :param test_only_changes: specifies if only condition-action combinations should be tested that invoke - a change (1), non changes (-1) or all possibilities (0) should be tested + :param test_only_changes: specifies if only condition-action + combinations should be tested that invoke a change (1), + non changes (-1) or all possibilities (0) should be tested """ logging.debug('Starting environment HandEye') self.grid_size = grid_size @@ -35,12 +38,16 @@ def __init__(self, grid_size, note_in_hand, test_only_changes=0): def step(self, action): """ Run one timestep of the environment's dynamics. - Accepts an action and returns a tuple (observation, reward, done, info). + Accepts an action and returns a tuple + (observation, reward, done, info). :param action: an action provided by the environment - :return: observation (tuple): agent's observation of the current environment + :return: observation (tuple): agent's observation of + the current environment reward (float) : amount of reward returned after previous action - done (boolean): whether the episode has ended, in which case further step() calls will return undefined results - info (dict): contains auxiliary diagnostic information (helpful for debugging, and sometimes learning) + done (boolean): whether the episode has ended, in which case + further step() calls will return undefined results + info (dict): contains auxiliary diagnostic information + (helpful for debugging, and sometimes learning) """ logging.debug('Executing a step, action = {}'.format(action)) @@ -71,6 +78,7 @@ def reset(self): def render(self, mode='human', close=False): """ Renders the environment. + :param mode: :param mode (str): the mode to render with :param close (bool): close all open renderings :return: @@ -124,32 +132,37 @@ def get_all_possible_transitions(self): Returns all possible transitions of the environment This information is used to calculate the agent's knowledge :param self - :return: all transitions as list of tuples: (start_state, action, end_state) + :return: all transitions as list of tuples: + (start_state, action, end_state) """ return utils.get_all_possible_transitions(self.grid_size) def get_goal_state(self): """ - Returns goal_state - an observation that is the environment's next goal. - Non deterministic. + Returns goal_state - an observation that is the environment's + next goal. Non deterministic. :return: """ return self.handeye.get_goal_state() def _should_end_testing(self, previous, obs): """ - Returns if the test should end based on self.test_only_changes parameter. + Returns if the test should end based on self.test_only_changes + parameter. :param previous: previous observation :param obs: current observation :return: """ - return (self.test_only_changes == 1 and not self._change_detected(previous, obs)) or ( - self.test_only_changes == -1 and self._change_detected(previous, obs)) + return (self.test_only_changes == 1 and not self._change_detected( + previous, obs)) or (self.test_only_changes == -1 and + self._change_detected(previous, obs)) - def _change_detected(self, previous, current): + @staticmethod + def _change_detected(previous, current): """ - Returns true if a change was detected between observations (previous and current). + Returns true if a change was detected between + observations (previous and current). :param previous: previous observation :param current: current observation :return: @@ -165,7 +178,8 @@ def _observe(self): def _take_action(self, action): """ - Executes an action with all consequences. Returns true if executing an action was successful. + Executes an action with all consequences. + Returns true if executing an action was successful. :param action: :return: """ diff --git a/gym_handeye/handeye_simulator.py b/gym_handeye/handeye_simulator.py index 5a014ef..f7b59f5 100644 --- a/gym_handeye/handeye_simulator.py +++ b/gym_handeye/handeye_simulator.py @@ -34,7 +34,8 @@ def __init__(self, grid_size, note_in_hand): """ :param grid_size: specifies the size of the monitored plain - :param note_in_hand: specifies if the tacticle sensor should switch to '2' if the block is held by the gripper + :param note_in_hand: specifies if the tacticle sensor should + switch to '2' if the block is held by the gripper (if False, then goes back to '0') """ self.grid_size = grid_size @@ -91,7 +92,8 @@ def take_action(self, action): def set_random_positions(self): """ - Non deterministic function, sets block on random position, then sets block in hand or not + Non deterministic function, sets block on random position, + then sets block in hand or not (if not in hand, then sets griper on random position). :return: observation after setting block and gripper """ @@ -113,7 +115,8 @@ def set_random_positions(self): def parse_observation(self, observation): """ - Function that sets current environment state so that it matches observation. + Function that sets current environment state so that it + matches observation. :param observation: list with observation space for this environment, ex. ['w', 'g', 'w', 'w', 'w', 'b', 'w', 'w', 'w', '0'] :return: @@ -147,7 +150,8 @@ def parse_observation(self, observation): def _move_gripper(self, x_end, y_end): """ Executes a moving action with all involved consequences. - Important: doesn't check if the moving action is possible (if the x_end, y_end position exists). + Important: doesn't check if the moving action is possible + (if the x_end, y_end position exists). :param x_end: End gripper x position :param y_end: End gripper y position :return: @@ -206,7 +210,8 @@ def _release_block(self): """ if self.block_in_hand: self._set_observation_gripper_state(BLOCK_UNDER_GRIPPER) - self._set_observation_grid(self.grip_pos_x, self.grip_pos_y, GRIPPER) + self._set_observation_grid(self.grip_pos_x, self.grip_pos_y, + GRIPPER) self.block_in_hand = False return True @@ -226,7 +231,8 @@ def _is_above_block(self): Checks if gripper is above block :return: True if gripper is above block """ - return self.block_pos_x == self.grip_pos_x and self.block_pos_y == self.grip_pos_y + return self.block_pos_x == self.grip_pos_x \ + and self.block_pos_y == self.grip_pos_y def _set_block_in_hand(self): """ @@ -259,11 +265,14 @@ def _set_block_not_in_hand(self): def _set_gripper_state(self, observation, state): """ Sets what gripper feels in 'observation' list. - :param state: BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND + :param state: BLOCK_NOT_UNDER_GRIPPER, + BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND :return: """ - if state not in [BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND]: - raise ValueError("State should be in [{}, {}, {}]".format(BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND)) + if state not in [BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, + BLOCK_IN_HAND]: + raise ValueError("State should be in [{}, {}, {}]".format( + BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND)) observation[self.env_size - 1] = state def _set_grid(self, observation, x, y, observe): @@ -275,7 +284,9 @@ def _set_grid(self, observation, x, y, observe): :return: """ if observe not in [BLOCK, GRIPPER, SURFACE]: - raise ValueError("Observation should be in [{}, {}, {}]".format(BLOCK, GRIPPER, SURFACE)) + raise ValueError( + "Observation should be in [{}, {}, {}]".format(BLOCK, GRIPPER, + SURFACE)) observation[y * self.grid_size + x] = observe def _set_observation_grid(self, x, y, observe): @@ -291,7 +302,8 @@ def _set_observation_grid(self, x, y, observe): def _set_observation_gripper_state(self, state): """ Sets what gripper feels in self.observation. - :param state: BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND + :param state: BLOCK_NOT_UNDER_GRIPPER, + BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND :return: """ self._set_gripper_state(self.observation, state) @@ -309,7 +321,8 @@ def _set_goal_grid(self, x, y, observe): def _set_goal_gripper_state(self, state): """ Sets what gripper feels in self.goal_state. - :param state: BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND + :param state: BLOCK_NOT_UNDER_GRIPPER, + BLOCK_UNDER_GRIPPER, BLOCK_IN_HAND :return: """ self._set_gripper_state(self.goal_state, state) @@ -378,7 +391,8 @@ def _state_grip_block(self): def _state_move_with_block(self): """ - Changes the goal_state: the gripper is moving with block in hand to random position. + Changes the goal_state: the gripper is moving with + block in hand to random position. :return: """ while True: @@ -401,7 +415,8 @@ def _state_release_block(self): def _state_move_not_over_block(self): """ - Changes the goal_state: the gripper is in random position not over block. + Changes the goal_state: the gripper is in random + position not over block. :return: """ while True: diff --git a/gym_handeye/tests/test_handeye.py b/gym_handeye/tests/test_handeye.py index 983b037..a4bda07 100644 --- a/gym_handeye/tests/test_handeye.py +++ b/gym_handeye/tests/test_handeye.py @@ -49,7 +49,7 @@ def test_execute_step(self): # then assert state is not None assert tuple == type(state) - assert done == False + assert done is False for i, obs in enumerate(state): if i < 9: assert obs in ['w', 'b', 'g'] diff --git a/gym_handeye/utils/utils.py b/gym_handeye/utils/utils.py index f082a74..e443d5e 100644 --- a/gym_handeye/utils/utils.py +++ b/gym_handeye/utils/utils.py @@ -1,5 +1,6 @@ import gym_handeye as he -from gym_handeye.handeye_simulator import SURFACE, BLOCK, GRIPPER, BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, \ +from gym_handeye.handeye_simulator import SURFACE, BLOCK, GRIPPER, \ + BLOCK_NOT_UNDER_GRIPPER, BLOCK_UNDER_GRIPPER, \ BLOCK_IN_HAND @@ -8,7 +9,8 @@ def get_all_possible_transitions(grid_size): Returns all possible transitions of environment This information is used to calculate the agent's knowledge :param grid_size: size of the grid - :return: all transitions as a list of tuples: (start_state, action, end_state) + :return: all transitions as a list of tuples: + (start_state, action, end_state) """ env_size = grid_size * grid_size + 1 states = [] @@ -54,4 +56,4 @@ def get_transitions(grid_size, start): states.append((tuple(start), action, tuple(end))) mock_handeye.parse_observation(start) - return states \ No newline at end of file + return states diff --git a/gym_maze/__init__.py b/gym_maze/__init__.py index be06cbb..0918ab0 100644 --- a/gym_maze/__init__.py +++ b/gym_maze/__init__.py @@ -88,4 +88,4 @@ def find_action_by_direction(direction): entry_point='gym_maze.envs:Woods14', max_episode_steps=50, nondeterministic=False -) \ No newline at end of file +) diff --git a/gym_maze/envs/MazeF3.py b/gym_maze/envs/MazeF3.py index 380a0cc..7c0021e 100644 --- a/gym_maze/envs/MazeF3.py +++ b/gym_maze/envs/MazeF3.py @@ -12,4 +12,4 @@ def __init__(self): [1, 0, 0, 0, 1, 1], [1, 0, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1], - ])) \ No newline at end of file + ])) diff --git a/gym_maze/envs/abstract_maze.py b/gym_maze/envs/abstract_maze.py index abcac54..85bd91d 100644 --- a/gym_maze/envs/abstract_maze.py +++ b/gym_maze/envs/abstract_maze.py @@ -84,8 +84,8 @@ def _is_over(self): def get_all_possible_transitions(self): """ Debugging only - - :return: + + :return: """ return get_all_possible_transitions(self) diff --git a/gym_maze/maze.py b/gym_maze/maze.py index bf59347..76549a9 100644 --- a/gym_maze/maze.py +++ b/gym_maze/maze.py @@ -6,7 +6,7 @@ class Maze: """ Creates new maze. - + Mapping: 0 - path 1 - wall diff --git a/gym_maze/utils/utils.py b/gym_maze/utils/utils.py index 28c758a..8402a60 100644 --- a/gym_maze/utils/utils.py +++ b/gym_maze/utils/utils.py @@ -10,7 +10,7 @@ def get_all_possible_transitions(maze): [POINT]->[ACTION]->[POINT] This information is used to calculate the agent's knowledge :param maze: an instance of the maze - :return: + :return: """ transitions = [] @@ -55,4 +55,4 @@ def _create_graph(env): g.add_edges_from(edges) - return g \ No newline at end of file + return g diff --git a/gym_multiplexer/__init__.py b/gym_multiplexer/__init__.py index ebab56a..127e005 100644 --- a/gym_multiplexer/__init__.py +++ b/gym_multiplexer/__init__.py @@ -57,4 +57,4 @@ entry_point='gym_multiplexer:RealMultiplexer', max_episode_steps=max_episode_steps, kwargs={'control_bits': 2} -) \ No newline at end of file +) diff --git a/gym_multiplexer/boolean_multiplexer.py b/gym_multiplexer/boolean_multiplexer.py index fecf09e..82bfd1b 100644 --- a/gym_multiplexer/boolean_multiplexer.py +++ b/gym_multiplexer/boolean_multiplexer.py @@ -13,7 +13,8 @@ def __init__(self, control_bits=3) -> None: self.action_space = Discrete(2) def _generate_state(self): - return [random.randint(0, 1) for _ in range(0, self._observation_string_length - 1)] + return [random.randint(0, 1) for _ in + range(0, self._observation_string_length - 1)] def _internal_state(self): - return list(map(lambda x: round(x), self._state)) + return list(map(lambda x: round(x), self._state)) diff --git a/gym_multiplexer/multiplexer.py b/gym_multiplexer/multiplexer.py index 5b3f4a1..ef2aebf 100644 --- a/gym_multiplexer/multiplexer.py +++ b/gym_multiplexer/multiplexer.py @@ -1,54 +1,58 @@ +from typing import List + import gym from .utils import get_correct_answer class Multiplexer(gym.Env): + metadata = {'render.modes': ['human', 'ansi']} + + REWARD = 1000 - REWARD = 1000 + def _generate_state(self): raise NotImplementedError - def _generate_state(self): raise NotImplementedError - def _internal_state(self): raise NotImplementedError + def _internal_state(self): raise NotImplementedError - def __init__(self, control_bits=3) -> None: - self.control_bits = control_bits - self.metadata = {'render.modes': ['human', 'ansi']} + def __init__(self, control_bits=3) -> None: + self.control_bits = control_bits - self._state = None - self._validation_bit = 0 + self._state: List = [] + self._validation_bit = 0 - def reset(self): - self._state = self._generate_state() - self._validation_bit = 0 - return self._observation + def reset(self): + self._state = self._generate_state() + self._validation_bit = 0 + return self._observation - def step(self, action): - reward = 0 + def step(self, action): + reward = 0 - if action == self._correct_answer: - self._validation_bit = 1 - reward = self.REWARD + if action == self._correct_answer: + self._validation_bit = 1 + reward = self.REWARD - return self._observation, reward, None, None + return self._observation, reward, True, None - def render(self, mode='human'): - if mode == 'human': - print(self._observation) - elif mode == 'ansi': - return self._observation - else: - super(Multiplexer, self).render(mode=mode) + def render(self, mode='human'): + if mode == 'human': + print(self._observation) + elif mode == 'ansi': + return self._observation + else: + super(Multiplexer, self).render(mode=mode) - @property - def _observation(self) -> list: - observation = list(self._state) - observation.append(self._validation_bit) - return observation + @property + def _observation(self) -> list: + observation = list(self._state) + observation.append(self._validation_bit) + return observation - @property - def _correct_answer(self): - return get_correct_answer(list(self._internal_state()) , self.control_bits) + @property + def _correct_answer(self): + return get_correct_answer(list(self._internal_state()), + self.control_bits) - @property - def _observation_string_length(self): - return self.control_bits + pow(2, self.control_bits) + 1 \ No newline at end of file + @property + def _observation_string_length(self): + return self.control_bits + pow(2, self.control_bits) + 1 diff --git a/gym_multiplexer/real_multiplexer.py b/gym_multiplexer/real_multiplexer.py index 26edf19..62dc0c8 100644 --- a/gym_multiplexer/real_multiplexer.py +++ b/gym_multiplexer/real_multiplexer.py @@ -8,16 +8,17 @@ class RealMultiplexer(Multiplexer): - def __init__(self, control_bits=3, threshold=.5) -> None: - super().__init__(control_bits) - self.threshold = threshold - self.observation_space = Box(low=0, high=1, - shape=(self._observation_string_length, ), - dtype=np.float32) - self.action_space = Discrete(2) + def __init__(self, control_bits=3, threshold=.5) -> None: + super().__init__(control_bits) + self.threshold = threshold + self.observation_space = Box(low=0, high=1, + shape=(self._observation_string_length,), + dtype=np.float32) + self.action_space = Discrete(2) - def _generate_state(self): - return [random.random() for _ in range(0, self._observation_string_length - 1)] + def _generate_state(self): + return [random.random() for _ in + range(0, self._observation_string_length - 1)] - def _internal_state(self): - return list(map(lambda x: x > self.threshold, self._state)) + def _internal_state(self): + return list(map(lambda x: x > self.threshold, self._state)) diff --git a/gym_multiplexer/tests/test_boolean_multiplexer.py b/gym_multiplexer/tests/test_boolean_multiplexer.py index a8f1167..cbd7630 100644 --- a/gym_multiplexer/tests/test_boolean_multiplexer.py +++ b/gym_multiplexer/tests/test_boolean_multiplexer.py @@ -33,7 +33,7 @@ def test_should_return_observation_when_reset(self): assert 7 == len(state) assert type(state) is list for obs in state: - assert obs in [0, 1] + assert obs in [0, 1] def test_should_render_state(self): # given @@ -64,7 +64,7 @@ def test_should_execute_step(self): assert reward in [0, 1000] assert done is True for obs in state: - assert obs in [0, 1] + assert obs in [0, 1] def test_execute_multiple_steps_and_keep_constant_perception_length(self): # given diff --git a/gym_multiplexer/tests/test_real_multiplexer.py b/gym_multiplexer/tests/test_real_multiplexer.py index b6ab851..de0eafe 100644 --- a/gym_multiplexer/tests/test_real_multiplexer.py +++ b/gym_multiplexer/tests/test_real_multiplexer.py @@ -9,60 +9,61 @@ logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) + class TestRealMultiplexer: - def test_should_initialize_real_mpx(self): - # when - mp = gym.make("real-multiplexer-6bit-v0") - - # then - assert mp is not None - assert (7,) == mp.observation_space.shape - assert 2 == mp.action_space.n - - def test_should_return_observation_when_reset(self): - # given - mp = gym.make('real-multiplexer-6bit-v0') - - # when - state = mp.reset() - - # then - assert state is not None - assert state[-1] == 0 - assert 7 == len(state) - assert type(state) is list - - def test_should_execute_step(self): - # given - mp = gym.make('real-multiplexer-6bit-v0') - mp.reset() - action = self._random_action() - - # when - state, reward, done, _ = mp.step(action) - - # then - assert state is not None - assert state[-1] in [0, 1] - assert type(state) is list - assert reward in [0, 1000] - assert done is True - - def test_execute_multiple_steps_and_keep_constant_perception_length(self): - # given - mp = gym.make('real-multiplexer-6bit-v0') - steps = 100 - - # when & then - for _ in range(0, steps): - p0 = mp.reset() - assert 7 == len(p0) - - action = self._random_action() - p1, reward, done, _ = mp.step(action) - assert 7 == len(p1) - - @staticmethod - def _random_action(): - return random.sample([0, 1], 1)[0] \ No newline at end of file + def test_should_initialize_real_mpx(self): + # when + mp = gym.make("real-multiplexer-6bit-v0") + + # then + assert mp is not None + assert (7,) == mp.observation_space.shape + assert 2 == mp.action_space.n + + def test_should_return_observation_when_reset(self): + # given + mp = gym.make('real-multiplexer-6bit-v0') + + # when + state = mp.reset() + + # then + assert state is not None + assert state[-1] == 0 + assert 7 == len(state) + assert type(state) is list + + def test_should_execute_step(self): + # given + mp = gym.make('real-multiplexer-6bit-v0') + mp.reset() + action = self._random_action() + + # when + state, reward, done, _ = mp.step(action) + + # then + assert state is not None + assert state[-1] in [0, 1] + assert type(state) is list + assert reward in [0, 1000] + assert done is True + + def test_execute_multiple_steps_and_keep_constant_perception_length(self): + # given + mp = gym.make('real-multiplexer-6bit-v0') + steps = 100 + + # when & then + for _ in range(0, steps): + p0 = mp.reset() + assert 7 == len(p0) + + action = self._random_action() + p1, reward, done, _ = mp.step(action) + assert 7 == len(p1) + + @staticmethod + def _random_action(): + return random.sample([0, 1], 1)[0] diff --git a/gym_multiplexer/tests/test_utils.py b/gym_multiplexer/tests/test_utils.py index f000de1..41439f9 100644 --- a/gym_multiplexer/tests/test_utils.py +++ b/gym_multiplexer/tests/test_utils.py @@ -4,11 +4,11 @@ class TestUtils: def test_should_calculate_correct_answer_for_3bit_multiplexer(self): - assert 1 == get_correct_answer([0,1,0,0], 1) - assert 0 == get_correct_answer([1,1,0,0], 1) + assert 1 == get_correct_answer([0, 1, 0, 0], 1) + assert 0 == get_correct_answer([1, 1, 0, 0], 1) def test_should_calculate_correct_answer_for_6bit_multiplexer(self): - assert 0 == get_correct_answer([1,1,0,1,0,0,0], 2) + assert 0 == get_correct_answer([1, 1, 0, 1, 0, 0, 0], 2) def test_should_calculate_correct_answer_for_11bit_multiplexer(self): - assert 1 == get_correct_answer([1,0,1,1,0,1,1,0,1,0], 3) + assert 1 == get_correct_answer([1, 0, 1, 1, 0, 1, 1, 0, 1, 0], 3) diff --git a/gym_multiplexer/utils/__init__.py b/gym_multiplexer/utils/__init__.py index cd0c665..9f383ae 100644 --- a/gym_multiplexer/utils/__init__.py +++ b/gym_multiplexer/utils/__init__.py @@ -1 +1 @@ -from .utils import get_correct_answer \ No newline at end of file +from .utils import get_correct_answer diff --git a/requirements.txt b/requirements.txt index be0797d..abcea91 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ -e . -pytest==3.2.3 \ No newline at end of file +mypy>=0.630 +pytest==3.2.3 +pytest-pep8>=1.0.6 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..46cd696 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[tool:pytest] +pep8ignore = E701 E704 + +[mypy] +python_version = 3.7 +ignore_missing_imports = true