### Complete Instance Configuration Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/setup_times.html Full example integrating problem specification, tool usage, and setup time matrices. ```yaml instance_config: description: "Example with setup times" instance: description: "3x3 problem" specification: | (m0,t)|(m1,t)|(m2,t) j0|(0,3) (1,2) (2,2) j1|(0,2) (2,1) (1,4) j2|(1,4) (2,3) (0,3) # Define which tool each operation uses tool_usage: - job: "j0" operation_tools: ["tl-0", "tl-1", "tl-2"] - job: "j1" operation_tools: ["tl-0", "tl-1", "tl-2"] - job: "j2" operation_tools: ["tl-0", "tl-1", "tl-2"] # Define setup time matrices setup_times: - machine: "m-0" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: static - machine: "m-1" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: type: "uni" offset: 2 ``` -------------------------------- ### begin_machine_setup Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/manipulate.html Initiates the setup process for a machine, transitioning it from IDLE to SETUP and calculating the required setup duration. ```APIDOC ## begin_machine_setup ### Description Handles the transition from IDLE to SETUP. This includes moving the job to the buffer, setting the machine state, calculating setup time based on tool changes, and updating the machine's mounted tool. ### Parameters - **instance** (InstanceConfig) - Required - The instance configuration containing setup time information. - **job_state** (JobState) - Required - The state of the job to process. - **machine_state** (MachineState) - Required - The machine state to update. - **time** (Time | NoTime) - Required - The current simulation time. ### Returns - **Tuple[JobState, MachineState]** - Updated job_state and machine_state. ``` -------------------------------- ### Setup development environment Source: https://proto-lab-ro.github.io/jobshoplab/additional_resources/contributing.html Commands to create a virtual environment and install development dependencies. ```bash python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -e .[dev] ``` -------------------------------- ### Handle Machine IDLE to SETUP Transition Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/handler.html Transitions a machine from IDLE to SETUP by moving a job from the prebuffer to the buffer and initiating setup. ```python [docs] def handle_machine_idle_to_setup_transition( state: State, instance: InstanceConfig, transition: ComponentTransition, machine: MachineState ) -> State: """ Handles the transition from machine IDLE to SETUP state. This function moves a job from the machine's prebuffer to its buffer and sets up the machine to start processing the job. It calculates setup times based on the tools needed for the operation. Args: state: Current state of the system instance: The instance configuration transition: The transition object containing component and job IDs machine: The machine state being transitioned Returns: State: Updated state after handling the transition Raises: InvalidValue: If transition has no job_id or job is not in prebuffer """ if transition.job_id is None: raise InvalidValue("job_id", None, "No job_id in transition") # Get the job state job_state = job_type_utils.get_job_state_by_id(jobs=state.jobs, job_id=transition.job_id) # Check if job is in prebuffer if not buffer_type_utils.is_job_in_buffer(machine.prebuffer, job_state.id): raise InvalidValue("job_location", job_state.location, "Job is not in machine's prebuffer") # Move job from prebuffer to buffer and start setup for operation job_state, _machine = manipulate.begin_machine_setup( job_state=job_state, instance=instance, machine_state=machine, time=state.time, ) # Update the state with new job and machine states state = possible_transition_utils.replace_job_state(state, job_state) state = possible_transition_utils.replace_machine_state(state, _machine) return state ``` -------------------------------- ### Begin Machine Setup Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/manipulate.html?q= Initiates the machine setup process, including tool change calculations and state transitions. ```python def begin_machine_setup( instance: InstanceConfig, job_state: JobState, machine_state: MachineState, time: Time | NoTime, ) -> Tuple[JobState, MachineState]: """ Start setting up a machine for a new operation. This function handles the transition from IDLE to SETUP by: 1. Moving the job from the machine's prebuffer to its buffer 2. Setting the machine state to SETUP 3. Calculating setup time based on tool change requirements 4. Setting the machine's occupied_till time based on the setup duration 5. Updating the machine's mounted tool 6. Setting the operation state to PROCESSING (during setup) Args: instance: The instance configuration containing setup time information job_state: The state of the job to process machine_state: The machine state to update time: The current simulation time Returns: Tuple containing updated job_state and machine_state """ # Get job and machine configurations job_configs = instance.instance.specification op_state = job_type_utils.get_next_not_done_operation(job_state) op_config = job_type_utils.get_operation_config_by_id(job_configs, op_state.id) machine_config = machine_type_utils.get_machine_config_by_id( instance.machines, machine_state.id ) # Calculate setup duration based on tool change current_time = time.time setup_duration = _get_setup_duration(machine_state, machine_config, operation_config=op_config) ``` -------------------------------- ### Retrieve default setup times Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/mapper.html?q= Calculates zero-duration setup times for all combinations of provided tools. ```python def _get_setup_times( self, tools: tuple[Tool, ...] ) -> Dict[tuple[Tool, Tool], DeterministicTimeConfig]: """ Get the setup times between products. Args: products (List[Product]): The list of products. Returns: Dict[tuple[Product, Product], DeterministicTimeConfig]: The setup times. """ setup_times = {} for tool in tools: for other_tool in tools: setup_times[(tool, other_tool)] = DeterministicTimeConfig(0) return setup_times ``` -------------------------------- ### Access Setup Times in Python Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/setup_times.html Retrieve and update setup time durations programmatically from the environment instance. ```python # Access setup time for a specific machine setup_times = env.instance.machines[1].setup_times # Get the time to change from tool1 to tool2 setup_duration = setup_times[("tl-0", "tl-1")].time # For stochastic setup times, you can see each update # The time is recalculated each time it's needed setup_times[("tl-0", "tl-1")].update() new_duration = setup_times[("tl-0", "tl-1")].time ``` -------------------------------- ### Create Machine Setup Transition Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/handler.html Defines the signature for creating a machine setup transition when a job is available. ```python def create_machine_setup_transition( all_buffer_configs: tuple[BufferConfig, ...], machine: MachineState ) -> Optional[ComponentTransition]: """ Create a machine setup transition if a job is available in the prebuffer. ``` -------------------------------- ### Install JobShopLab Source: https://proto-lab-ro.github.io/jobshoplab/index.html Commands to clone the repository and install the package in editable mode. ```bash cd # ssh git clone git@github.com:proto-lab-ro/jobshoplab.git # or https git clone https://github.com/proto-lab-ro/jobshoplab.git # install python module in edible mode pip install -e ``` -------------------------------- ### Handle Machine SETUP to WORKING Transition Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/handler.html Handles the transition from machine SETUP to WORKING state, updating job and machine status. ```python [docs] def handle_machine_setup_to_working_transition( state: State, instance: InstanceConfig, transition: ComponentTransition, machine: MachineState ) -> State: """ Handles the transition from machine SETUP to WORKING state. This function moves a job from setup phase to active processing. It updates both job and machine state to reflect the new processing status and calculates the operation duration. ``` -------------------------------- ### Define Setup Times in DSL Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/setup_times.html Configure static or stochastic setup time matrices for machines using the setup_times section. ```yaml setup_times: - machine: "m-0" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: static - machine: "m-1" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: type: "uni" offset: 2 - machine: "m-2" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: type: "uni" offset: 2 ``` -------------------------------- ### Calculate Setup Duration Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/manipulate.html?q= Determines the time required to change tools, supporting both deterministic and stochastic setup time configurations. ```python # Get the tools involved in the setup new_tool = operation_config.tool old_tool = machine_state.mounted_tool # Get the setup time for changing from old_tool to new_tool s_time = machine_config.setup_times.get((old_tool, new_tool)) # Handle different types of setup times match s_time: case DeterministicTimeConfig(): return s_time.time case StochasticTimeConfig(): s_time.update() return s_time.time case _: if s_time is None: raise InvalidValue( key=(old_tool, new_tool), value=None, message="setup time not found in mapping (check instance mapping)", ) raise InvalidSetupTimeTypeError( type(s_time), "DeterministicTimeConfig or StochasticTimeConfig" ) ``` -------------------------------- ### Create Machine Setup Transition Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/handler.html Determines if a machine can transition from idle to setup based on job availability in the prebuffer. Only supports automatic scheduling buffer types. ```python transition = None if len(machine.prebuffer.store) > 0: prebuffer_config = buffer_type_utils.get_buffer_config_by_id( all_buffer_configs, machine.prebuffer.id ) # Determine if automatic transition should be created based on buffer type next_job_id = buffer_type_utils.get_next_job_from_buffer( machine.prebuffer, prebuffer_config ) if next_job_id is not None: # FIFO/LIFO/DUMMY, not flex transition = ComponentTransition( component_id=machine.id, new_state=MachineStateState.SETUP, job_id=next_job_id, ) return transition ``` -------------------------------- ### Start Dashboard from File Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Loads job shop data from a pickle file and initializes the dashboard. ```python def start_dashboard_from_file(file_path: str, debug: bool, port: int) -> None: """ Start the dashboard from a data file. Args: file_path: Path to the data file. debug: Flag to enable debug mode. port: Port number for the dashboard server. Raises: FileNotFound: If the file does not exist. Exception: If the file cannot be loaded. """ path = Path(file_path) if not path.exists(): raise FileNotFound(path) logger = get_logger("FileLoad", "INFO") try: with open(path, "rb") as f: data, num_jobs, num_machines, current_time = pickle.load(f) except Exception as e: logger.error(f"Error loading file {file_path}: {e}") raise has_transports = DashboardUtils.has_transports(data) dashboard = JobShopDashboard( data, num_machines, num_jobs, current_time, has_transports, debug, port ) dashboard.run() ``` -------------------------------- ### Configure Stochastic Setup Times Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/setup_times.html Apply a Gaussian distribution to base setup matrix values to model variability. ```yaml setup_times: - machine: "m-2" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: type: "gaussian" mean: 1.0 std: 0.2 ``` -------------------------------- ### Simulate Complete Workflow Source: https://proto-lab-ro.github.io/jobshoplab/additional_resources/release_notes.html?q= Example of initializing the environment with output buffer configurations and running a simulation loop. ```python # New realistic simulation flow from jobshoplab import JobShopLabEnv, load_config config = load_config("config_with_output_buffers.yaml") env = JobShopLabEnv(config) obs, info = env.reset() while not env._is_terminated(): action = agent.select_action(obs) obs, reward, terminated, truncated, info = env.step(action) # All jobs now guaranteed to be at output buffers print("Complete workflow simulation finished!") ``` -------------------------------- ### InstanceRandomizer Usage Example Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/manipulators.html Demonstrates how to initialize an environment and apply the InstanceRandomizer to manipulate instance configurations. ```python if __name__ == "__main__": from jobshoplab.env.env import JobShopLabEnv env = JobShopLabEnv() state = env.state instance = env.instance instance_randomizer = InstanceRandomizer(loglevel="debug", config=env.config) new_instance, new_state = instance_randomizer.manipulate( instance_config=instance, init_state=state ) assert ( new_instance.instance.specification[1].operations != instance.instance.specification[1].operations ) ``` -------------------------------- ### Full Outage Implementation Example Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/outages.html A complete configuration example demonstrating multiple outage types applied to machines and transport units. ```yaml instance_config: # Standard job and machine definitions... outages: # Regular maintenance for all machines - component: "m" type: "maintenance" duration: 5 frequency: 100 # Random failures for machine 0 - component: "m-0" type: "fail" duration: type: "gaussian" mean: 8 std: 2 frequency: type: "gamma" shape: 3 scale: 10 # Recharging for AGVs - component: "t" type: "recharge" duration: 10 frequency: 50 ``` -------------------------------- ### Example Usage of render_state_transitions Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/state_transitions_rendering.html Demonstrates how to invoke the rendering function with a file-saving backend. ```python if __name__ == "__main__": from jobshoplab.env.rendering.backends import save_to_file config = load_config() args = {"instance": None, "name": "state_transition_graph_representation"} backend = partial(save_to_file, **args) render_state_transitions(config, 0, backend=backend) ``` -------------------------------- ### Parse Setup Times Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/mapper.html?q= Parses a string representation of setup times into a mapping of machine pairs to time configurations. ```python def _parse_setup_times( self, setup_times_str: str, time_behavior: str | dict ) -> Mapping[tuple[str, str], DeterministicTimeConfig | StochasticTimeConfig]: # self.logger.debug("Parse logistics specification") # if not self.has_key(("instance_config", "logistics", "specification"), spec_dict): # raise ValueError("Logistics specification must be provided.") # if self.has_key(("instance_config", "logistics", "time_behavior"), spec_dict): # time_behavior = spec_dict["instance_config"]["logistics"]["time_behavior"] # else: # time_behavior = "static" lines = [line.strip() for line in setup_times_str.strip().split("\n")] headers = lines[0].split("|") # Get machine names from the header row # Create a dictionary to map each (machine1, machine2) tuple to its value mapper = {} for line in lines[1:]: parts = line.split("|") row_name = parts[0] values = map(int, parts[1].split()) for col_name, value in zip(headers, values): mapper[(row_name, col_name)] = self._get_time(value, time_behavior) return mapper ``` -------------------------------- ### Calculate Setup Duration Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/state_machine/core/state_machine/manipulate.html?q= Calculates the time required for a machine to change tools. ```python def _get_setup_duration( machine_state: MachineState, machine_config: MachineConfig, operation_config: OperationConfig ) -> int: """ Calculate the setup time for a machine to change tools. ``` -------------------------------- ### Configure Stochastic Setup Times Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/stochastic_time_behavior.html Applies a uniform distribution to machine setup times using the matrix values as the lower bound. ```yaml setup_times: - machine: "m-1" specification: | tl-0|tl-1|tl-2 tl-0|0 2 5 tl-1|2 0 8 tl-2|5 2 0 time_behavior: type: "uniform" offset: 2 ``` -------------------------------- ### Validate setup time specification string Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/validators.html Validates the syntax of an individual setup time specification string, checking for correct tool header formatting. ```python def _validate_setup_time_specification(self, specification: str, index: int) -> None: """ Validates a setup time specification string. Args: specification (str): The setup time specification. index (int): The index of the setup time in the setup_times list. Raises: InstanceSchemaError: For schema-related errors. """ # Split the specification into lines and remove leading/trailing whitespace lines = [line.strip() for line in specification.strip().split("\n")] # Skip empty lines lines = [line for line in lines if line] if not lines: raise InstanceSchemaError( f"Empty setup time specification for setup_times[{index}]", f"setup_times[{index}].specification", ) # First line should be the tool header header = lines[0].split("|") if len(header) < 2: raise InstanceSchemaError( f"Invalid tool header format for setup_times[{index}] - must contain at least two tools separated by '|'", f"setup_times[{index}].specification", ) num_tools = len(header) ``` -------------------------------- ### Configure Event-Based Binary Action Middleware Source: https://proto-lab-ro.github.io/jobshoplab/concepts/middleware.html Example configuration for the EventBasedBinaryActionMiddleware in a YAML-like structure. ```yaml env: middleware: "EventBasedBinaryActionMiddleware" middleware: event_based_binary_action_middleware: truncation_joker: 5 truncation_active: False ``` -------------------------------- ### Run Dashboard Application Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Starts the dashboard application instance. ```python def run(self) -> None: """ Run the dashboard application. ``` -------------------------------- ### Machine Configuration asdict Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/types/instance_config_types.html?q= Serializes the machine configuration, including setup times and buffer settings, into a dictionary. ```python def asdict(self) -> dict: return { "id": self.id, "outages": tuple(o.asdict() for o in self.outages), "setup_times": {f"{t1}_{t1}": st.asdict() for (t1, t2), st in self.setup_times.items()}, "prebuffer": self.prebuffer.asdict(), "postbuffer": self.postbuffer.asdict(), "batches": self.batches, "resources": tuple(r.asdict() for r in self.resources), "buffer": self.buffer.asdict(), "description": self.description, } ``` -------------------------------- ### Setup Dashboard Layout Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Configures the Dash application layout by initializing data stores and the main dashboard header. ```python def _setup_layout(self) -> None: """Set up the layout for the Dash application.""" table_data = [ dict(item) for item in self.data["schedules"] + self.data["transports"] + self.data["buffer"] ] self.app.layout = html.Div( [ dcc.Store(id=self.store_data_id, data=self.data), dcc.Store(id=self.store_current_time_id, data=self.current_time), dcc.Store(id=self.store_num_machines_id, data=self.num_machines), dcc.Store(id=self.store_num_jobs_id, data=self.num_jobs), html.H1( f"JobShopLab Dashboard for {self.num_machines[0]} machines and {self.num_jobs} jobs", ``` -------------------------------- ### Define Tool Usage Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/setup_times.html Map operations within jobs to specific tools to enable setup time calculations. ```yaml tool_usage: - job: "j0" operation_tools: ["tl-0", "tl-1", "tl-2"] - job: "j1" operation_tools: ["tl-0", "tl-1", "tl-2"] - job: "j2" operation_tools: ["tl-0", "tl-1", "tl-2"] ``` -------------------------------- ### Environment Reset Logic Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/env.html Handles the initialization of the environment state, including dependency building, instance compilation, and factory setup. ```python Returns: tuple[np.ndarray, dict]: A tuple containing: - Initial observation [dict space] - Empty info dictionary """ self.episode_counter += 1 builder = DependencyBuilder(self.init_args["config"], self.init_args["loglevel"]) self.config: Config = builder.config(self.init_args["config"]) self.loglevel: int | str = builder.loglevel(self.init_args["loglevel"]) self.logger = builder.logger(self.loglevel) if hasattr(self, "seed") and seed is None: seed = self.seed self.seed: int | None = builder.seed( seed + self.episode_counter if seed is not None else None ) compiler: Compiler = builder.compiler(self.init_args["compiler"]) # getting instance config and init state for further initialization self.instance: InstanceConfig _init_state: any self.instance, _init_state = compiler.compile() ### instance based static values self.lower_bound: int = builder.lower_bound(self.instance) self.max_allowed_time: int = builder.max_allowed_time(self.instance) self.num_operations: int = builder.num_operations(self.instance) # getting factories observation_factory: observations.ObservationFactory = builder.observation_factory( self.init_args["observation_factory"], self.loglevel, self.instance ) self.reward_factory: rewards.RewardFactory = builder.reward_factory( self.init_args["reward_factory"], self.loglevel, self.instance, self.max_allowed_time ) self.render_backend: Callable = builder.render_backend( self.init_args["render_backend"], self.loglevel, self.instance ) # build state machine and action_factory action_factory: action_factory_collection.ActionFactory = builder.action_factory( self.init_args["action_factory"], self.loglevel, self.instance ) self.state_simulator: middleware_collection.Middleware = builder.state_simulator( self.init_args["middleware"], self.loglevel, self.instance, action_factory, observation_factory, ) self.init_state: StateMachineResult current_observation: np.ndarray self.init_state, current_observation = self.state_simulator.reset(_init_state) # setting init state history and flags self.observation_space: gym.Space = observation_factory.observation_space self.action_space: gym.Space = action_factory.action_space self.state: StateMachineResult = self.init_state self.history: tuple[StateMachineResult, ...] = tuple() self.truncated: bool = False self.terminated: bool = False self.done = False return current_observation, { "env_seed": self.seed, "random_first_state": random.getstate()[1][0], "torch_seed": torch.initial_seed(), "torch_rng_state": torch.get_rng_state()[0].item(), } ``` -------------------------------- ### Implement Real-World Scaliro Protolab Instance Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/custom_instances.html?q= A comprehensive configuration example featuring travel time matrices, stochastic outages, and custom buffer management. ```yaml # Reference: data/jssp_instances/dsl/real_world_instance.yaml instance_config: description: "protolab config for scaliro" instance: description: "6x6" specification: | (m0,t)|(m1,t)|(m2,t)|(m3,t)|(m4,t)|(m5,t) j0|(2,1) (0,3) (1,6) (3,7) (5,3) (4,6) # ... additional jobs transport: type: "agv" amount: 6 # Travel time matrix from real measurements logistics: specification: | m-0|m-1|m-2|m-3|m-4|m-5|b-0|b-1|b-2|b-3|b-4|b-5 m-0| 0 21 16 9 37 41 12 18 22 15 28 31 # ... complete matrix # Machine maintenance and AGV recharging outages: - component: "m" type: "maintenance" duration: type: "poisson" base: 1 frequency: type: "uni" offset: 20 base: 50 - component: "t" type: "recharge" duration: type: "gaussian" std: 1 base: 5 frequency: type: "gaussian" std: 3 base: 40 # Custom buffer configuration buffer: - name: "b-0" type: "fifo" capacity: 1 # ... additional buffers # Machine buffer configuration machines: prebuffer: - capacity: 5 type: "fifo" postbuffer: - capacity: 5 type: "fifo" init_state: # Jobs start in dedicated buffers b-0: store: [j-0] j-0: location: b-0 # AGVs positioned at machines t-0: location: m-0 # ... additional initialization ``` -------------------------------- ### Group operations by start time Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/utils/solutions.html Organizes a list of (machine, job, start_time) tuples into a dictionary keyed by start time. ```python def group_by_time(tuples): """ Groups a list of tuples by their start time. Args: tuples (list of tuple): A list where each tuple contains three elements: - machine: The machine identifier. - job: The job identifier. - start_time: The start time of the job on the machine. Returns: dict: A dictionary where the keys are start times and the values are lists of tuples, each containing a machine and a job that start at that time. start_time = [(machine, job), ...] """ grouped = defaultdict(list) # Loop through each tuple in the input for machine, job, start_time in tuples: # Group by start_time grouped[start_time].append((machine, job)) return dict(grouped) ``` -------------------------------- ### JobShopDashboard.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Initializes the JobShopDashboard instance, sets up the Dash application, and registers callbacks for interactive components. ```APIDOC ## JobShopDashboard.__init__ ### Description Initializes the dashboard with scheduling data and configuration parameters. This method sets up the internal Dash application and generates unique IDs for interactive components. ### Parameters - **data** (Dict[str, Any]) - Required - Dictionary containing schedule, transport, and buffer data. - **num_machines** (Tuple[int]) - Required - Tuple containing the number of machines. - **num_jobs** (int) - Required - Number of jobs in the instance. - **current_time** (Any) - Required - Current time reference. - **has_transports** (bool) - Required - Boolean indicating if transport data is present. - **debug** (bool) - Required - Boolean flag for debug mode. - **port** (int) - Required - Port number for the dashboard server. ``` -------------------------------- ### Build documentation locally Source: https://proto-lab-ro.github.io/jobshoplab/additional_resources/contributing.html Commands to navigate to the docs directory and build the HTML documentation. ```bash # Navigate to the docs directory cd docs # Build the documentation make clean && make html ``` -------------------------------- ### Validate setup times configuration Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/validators.html Validates that the setup times configuration is a list of dictionaries containing required machine and specification fields. ```python def _validate_setup_times(self, setup_times: list) -> None: """ Validates the setup times configuration. Args: setup_times (list): The setup times configuration. Raises: InstanceSchemaError: For schema-related errors. """ # If it's a list, each item should have a 'machine' and 'specification' field if isinstance(setup_times, list): for i, setup in enumerate(setup_times): if not isinstance(setup, dict): raise InstanceSchemaError( f"Setup time entry {i+1} must be a dictionary", "setup_times" ) if "machine" not in setup: raise MissingRequiredFieldError("machine", f"setup_times[{i}]") if "specification" not in setup: raise MissingRequiredFieldError("specification", f"setup_times[{i}]") # Validate the specification format self._validate_setup_time_specification(setup["specification"], i) ``` -------------------------------- ### Load configuration and initialize environment Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/getting_started.html?q= Demonstrates loading a YAML configuration file and initializing the JobShopLab environment. Note that the configuration object is immutable. ```python from jobshoplab import JobShopLabEnv, load_config from pathlib import Path # Load the configuration file. config = load_config(config_path=Path("./data/config/getting_started_config.yaml")) # Access config attributes using dot notation. print(f"Dashboard Port: {config.render_backend.render_in_dashboard.port}") # The configuration is immutable to prevent accidental changes. try: config.render_backend.render_in_dashboard.port = 1000 except AttributeError as e: print(f"Error: {e}") # Create an environment with the loaded configuration. env = JobShopLabEnv(config=config) ``` -------------------------------- ### Update machine configuration with outages and setup times Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/mapper.html?q= Updates a MachineConfig object by applying outage and setup time specifications found in a dictionary. ```python def _add_machine_spec(self, default: MachineConfig, spec_dict: Dict) -> MachineConfig: machine = default if self.has_key(("instance_config", "outages"), spec_dict): component_list = ["m", "machine", "Machine", "MACHINE", machine.id] outages = self._map_spec_dict_to_outage(spec_dict, component_list, default.outages) machine = replace(machine, outages=outages) if self.has_key(("instance_config", "setup_times"), spec_dict): setup_times_str = spec_dict["instance_config"]["setup_times"] setup_times_str = next( filter(lambda i: i["machine"] == machine.id, setup_times_str), None ) if setup_times_str is None: raise InvalidSetupTimesError(machine.id) if "time_behavior" in setup_times_str.keys(): _time_behavior = setup_times_str["time_behavior"] else: _time_behavior = "static" setup_times = self._parse_setup_times(setup_times_str["specification"], _time_behavior) machine = replace(machine, setup_times=setup_times) # Handle machine buffer configurations machine = self._apply_machine_buffer_config(machine, spec_dict) return machine ``` -------------------------------- ### Environment Execution Loop Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/env.html Demonstrates initializing the environment with a configuration file and running a basic simulation step loop. ```python if __name__ == "__main__": # from jobshopsimulation.utils.utils import make_json_dump config = load_config(config_path="data/config/config_scaliro.yaml") env = JobShopLabEnv(config) obs, info = env.reset() done = False while not done: action = 1 obs, reward, terminated, truncated, inf = env.step(action) done = terminated or truncated env.render() ``` -------------------------------- ### Validate setup time lines Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/validators.html Parses and validates the format and content of setup time lines, ensuring tools exist in the header and times are valid integers. ```python # Check each setup time line for i, line in enumerate(lines[1:], 1): parts = line.split("|") if len(parts) != 2: raise InstanceSchemaError( f"Invalid setup time line format at line {i+1}: '{line}'", f"setup_times[{index}].specification", ) tool = parts[0] if tool not in header: raise InstanceSchemaError( f"Unknown tool '{tool}' at line {i+1}", f"setup_times[{index}].specification" ) times = parts[1].split() if len(times) != num_tools: raise InstanceSchemaError( f"Setup time line {i+1} has {len(times)} times, but there are {num_tools} destination tools", f"setup_times[{index}].specification", ) # Check that times are integers for time in times: try: int(time) except ValueError: raise InstanceSchemaError( f"Setup time '{time}' at line {i+1} is not a valid integer", f"setup_times[{index}].specification", ) ``` -------------------------------- ### JobShopLabEnv.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/env.html?q= Initializes the JobShopLab environment with optional configurations, factories, and middleware. ```APIDOC ## __init__(config=None, seed=None, compiler=None, observation_factory=None, reward_factory=None, middleware=None, action_factory=None, render_backend=None, loglevel=None) ### Description Initializes a new instance of the JobShopLabEnv environment. ### Parameters - **config** (Config) - Optional - Configuration object containing environment parameters. - **seed** (int) - Optional - Random seed for reproducibility. - **compiler** (Compiler) - Optional - Instance compiler to parse problem instances. - **observation_factory** (observations.ObservationFactory) - Optional - Factory for creating observations. - **reward_factory** (rewards.RewardFactory) - Optional - Factory for calculating rewards. - **middleware** (middleware_collection.Middleware) - Optional - Middleware for state transitions. - **action_factory** (actions.ActionFactory) - Optional - Factory for actions. - **render_backend** (Callable) - Optional - Function for rendering the environment. - **loglevel** (int|str) - Optional - Logging level. ``` -------------------------------- ### Initialize and Run JobShopLab Environment Source: https://proto-lab-ro.github.io/jobshoplab/index.html Basic usage pattern for loading a configuration, creating the environment, and executing a loop with random actions. ```python from jobshoplab import JobShopLabEnv, load_config from pathlib import Path # Load a pre-defined configuration config = load_config(config_path=Path("./data/config/getting_started_config.yaml")) # Create the environment env = JobShopLabEnv(config=config) # Run with random actions until done done = False while not done: action = env.action_space.sample() obs, reward, truncated, terminated, info = env.step(action) done = truncated or terminated # Visualize the final schedule env.render() ``` -------------------------------- ### Define InvalidSetupTimeTypeError Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/utils/exceptions.html Exception raised when an invalid setup time type is provided. ```python class InvalidSetupTimeTypeError(JobShopException): def __init__(self, actual_type, expected_types=None): type_info = f"Expected {expected_types}" if expected_types else "" self.message = f"Invalid setup time type: {actual_type}. {type_info}" super().__init__(self.message) ``` -------------------------------- ### Get Environment Configuration Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/env.html Retrieves the current configuration object associated with the environment. ```python def get_config(self) -> Config: """ Get the current environment configuration. Returns: Config: The configuration object for this environment """ return self.config ``` -------------------------------- ### JobShopLabEnv.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/modules/jobshoplab.env.html Initializes the JobShopLabEnv environment with the specified configuration and factory components. ```APIDOC ## JobShopLabEnv.__init__ ### Description Initializes a new instance of the JobShopLabEnv environment for reinforcement learning. ### Parameters - **config** (Config, optional) - Configuration object containing environment parameters. - **seed** (int, optional) - Random seed for reproducibility. - **compiler** (Compiler, optional) - Compiler instance for processing job shop problems. - **observation_factory** (ObservationFactory, optional) - Factory class for creating observations. - **reward_factory** (RewardFactory, optional) - Factory class for calculating rewards. - **middleware** (Middleware, optional) - Middleware component for pre/post processing. - **action_factory** (ActionFactory, optional) - Factory component for action processing. - **render_backend** (Callable, optional) - Backend function for visualization. - **loglevel** (int | str, optional) - Logging level for the environment. ``` -------------------------------- ### Initialize DSL Instances via Dependency Injection Source: https://proto-lab-ro.github.io/jobshoplab/user_guide/custom_instances.html?q= Programmatically load a DSL file using the DslRepository. ```python from jobshoplab.compiler.repos import DslRepository repo = DslRepository(dir=Path("path/to/your/instance.yaml"), loglevel="warning", config=config) compiler = Compiler(config=config, loglevel="warning", repo=repo) env = JobShopLabEnv(config=config, compiler=compiler) ``` -------------------------------- ### Initialize Job Locations Source: https://proto-lab-ro.github.io/jobshoplab/additional_resources/dsl_reference.html?q= Sets the starting location for individual jobs within the system. ```yaml init_state: j-0: # Job ID location: b-0 # Initial location j-1: location: b-0 j-2: location: t-0 # Job being transported ``` -------------------------------- ### Main Entry Point Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Executes the dashboard application using CLI arguments. ```python def main() -> None: """ Main entry point for the dashboard application. """ args = parse_cli_arguments() try: start_dashboard_from_file(args.file_path, args.debug, args.port) except Exception as e: logger = get_logger("Main", "ERROR") logger.error(f"Dashboard failed to start: {e}") if __name__ == "__main__": main() ``` -------------------------------- ### group_by_time(tuples) Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/utils/solutions.html?q= Groups a list of (machine, job, start_time) tuples by their start time. ```APIDOC ## group_by_time(tuples) ### Description Organizes a list of operation tuples into a dictionary keyed by start time. ### Parameters - **tuples** (list of tuple) - Required - A list where each tuple contains (machine, job, start_time). ### Returns - **dict** - A dictionary where keys are start times and values are lists of (machine, job) tuples. ``` -------------------------------- ### Initialize compiler Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/env.html Creates a compiler instance using the environment configuration or a default log level. ```python def compiler(self, compiler: Optional[Compiler]) -> Compiler: complier_loglevel = ( self._config.compiler.loglevel if hasattr(self._config.compiler, "loglevel") else self._config.default_loglevel ) if compiler is None: compiler = Compiler( config=self._config, loglevel=complier_loglevel, ) return compiler ``` -------------------------------- ### EventBasedBinaryActionMiddleware.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab.state_machine.middleware.html Initializes the middleware with configuration, factories, and truncation settings. ```APIDOC ## __init__(loglevel, config, instance, truncation_joker, truncation_active, action_factory, observation_factory, state_machine_step, *args, **kwargs) ### Description Initializes the event-based binary action middleware with the necessary factories and configuration for state machine interaction. ### Parameters - **loglevel** (int | str) - Logging level for middleware operations - **config** (Config) - Global configuration settings - **instance** (InstanceConfig) - Problem instance configuration - **truncation_joker** (int) - Number of allowed truncations before episode termination - **truncation_active** (bool) - Whether to enable truncation - **action_factory** (BinaryJobActionFactory) - Factory for creating/interpreting binary actions - **observation_factory** (ObservationFactory) - Factory for creating observations from states - **state_machine_step** (Callable) - Function to execute state machine steps ``` -------------------------------- ### Get Processing Operation Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/utils/state_machine_utils/job_type_utils.html?q= Retrieves the operation currently in the PROCESSING state for a given job. ```python def get_processing_operation(job: JobState) -> OperationState | None: """ Get the active operation from a job. Args: job (JobState): The job to get the active operation from. Returns: OperationState: The active operation from the job. Raises: InvalidValue: If the job has no active operations. """ operations = job.operations active_operation = next( filter(lambda op: op.operation_state_state == OperationStateState.PROCESSING, operations), None, ) if active_operation is None: return None return active_operation ``` -------------------------------- ### Compiler.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/compiler/compiler.html Initializes the Compiler instance with a configuration, optional repository, and logging settings. ```APIDOC ## Compiler.__init__(config, loglevel='INFO', repo=None) ### Description Initializes the Compiler object, setting up the repository, validators, and mappers based on the provided configuration. ### Parameters - **config** (Config) - Required - The configuration object defining the compiler settings. - **loglevel** (int | str) - Optional - The log level for the compiler. Defaults to "INFO". - **repo** (repos.Repository) - Optional - A custom repository instance. If None, one is instantiated based on the config. ``` -------------------------------- ### JobShopLabEnv.__init__ Source: https://proto-lab-ro.github.io/jobshoplab/modules/jobshoplab.env.html?q= Initializes the JobShopLabEnv environment with the specified configuration, factories, and middleware components. ```APIDOC ## JobShopLabEnv.__init__ ### Description Initializes the JobShopLabEnv environment for reinforcement learning, setting up simulation components, observation generation, reward calculation, and visualization. ### Parameters - **config** (Config, optional) - Configuration object containing environment parameters. - **seed** (int, optional) - Random seed for reproducibility. - **compiler** (Compiler, optional) - Compiler instance for processing job shop problems. - **observation_factory** (ObservationFactory, optional) - Factory class for creating observations. - **reward_factory** (RewardFactory, optional) - Factory class for calculating rewards. - **middleware** (Middleware, optional) - Middleware component for pre/post processing. - **action_factory** (ActionFactory, optional) - Factory component for action processing. - **render_backend** (Callable, optional) - Backend function for visualization. - **loglevel** (int | str, optional) - Logging level for the environment. ``` -------------------------------- ### Define a well-formatted function Source: https://proto-lab-ro.github.io/jobshoplab/additional_resources/contributing.html Example of a function adhering to type annotation and Google-style docstring requirements. ```python def multiply(a: int, b: int) -> int: """ Multiplies two numbers and returns the result. Args: a (int): The first number. b (int): The second number. Returns: int: The product of a and b. """ return a * b ``` -------------------------------- ### start_dashboard_from_file(file_path: str, debug: bool, port: int) -> None Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/env/rendering/gant_dashboard.html Starts the dashboard server by loading data from a specified file path. ```APIDOC ## start_dashboard_from_file ### Description Loads dashboard data from a binary file and initializes the JobShopDashboard server. ### Parameters - **file_path** (str) - Required - Path to the data file. - **debug** (bool) - Required - Flag to enable debug mode. - **port** (int) - Required - Port number for the dashboard server. ### Raises - **FileNotFound** - If the file does not exist. - **Exception** - If the file cannot be loaded. ``` -------------------------------- ### Execute Complete JobShopLab Workflow Source: https://proto-lab-ro.github.io/jobshoplab/concepts/output_buffer_completion.html Initializes the environment using a configuration file and runs a simulation loop until all jobs reach the output buffers. ```python from jobshoplab import JobShopLabEnv, load_config # Load configuration with output buffers config = load_config("config_with_output_buffers.yaml") env = JobShopLabEnv(config) obs, info = env.reset() done = False while not done: action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) done = terminated or truncated # All jobs are now in output buffers print("All jobs successfully delivered to output buffers!") ``` -------------------------------- ### Get component type integer Source: https://proto-lab-ro.github.io/jobshoplab/_modules/jobshoplab/utils/utils.html Maps a component ID prefix to a float representation of its type. ```python def get_component_type_int(id: str) -> float: """ Get the integer representation of a component type from its ID. Args: id: The component ID string (format: [a-z]-[number]) Returns: int: Integer code for the component type (0 for machine, 1 for transport, 2 for buffer) Raises: InvalidValue: If the component type is invalid """ component_str = id.split("-")[0] match component_str: case "m": return 0.0 case "t": return 0.33 case "b": return 0.66 case _: raise InvalidValue(f"Invalid component id {id}", id) ```