"""Home of the `Node` class."""fromjob_shop_libimportOperationfromjob_shop_lib.exceptionsimport(UninitializedAttributeError,ValidationError,)fromjob_shop_lib.graphs._constantsimportNodeType
[docs]classNode:"""Represents a node in the :class:`JobShopGraph`. A node is hashable by its id. The id is assigned when the node is added to the graph. The id must be unique for each node in the graph, and should be used to identify the node in the networkx graph. Depending on the type of the node, it can have different attributes. The following table shows the attributes of each type of node: +----------------+---------------------+ | Node Type | Required Attribute | +================+=====================+ | OPERATION | ``operation`` | +----------------+---------------------+ | MACHINE | ``machine_id`` | +----------------+---------------------+ | JOB | ``job_id`` | +----------------+---------------------+ In terms of equality, two nodes are equal if they have the same id. Additionally, one node is equal to an integer if the integer is equal to its id. It is also hashable by its id. This allows for using the node as a key in a dictionary, at the same time we can use its id to index that dictionary. Example: .. code-block:: python node = Node(NodeType.SOURCE) node.node_id = 1 graph = {node: "some value"} print(graph[node]) # "some value" print(graph[1]) # "some value" Args: node_type: The type of the node. See :class:`NodeType` for theavailable types. operation: The operation of the node. Required if ``node_type`` is :attr:`NodeType.OPERATION`. machine_id: The id of the machine. Required if ``node_type`` is :attr:`NodeType.MACHINE`. job_id: The id of the job. Required if ``node_type`` is :attr:`NodeType.JOB`. Raises: ValidationError: If the ``node_type`` is :attr:`NodeType.OPERATION`, :attr:`NodeType.MACHINE`, or :attr:`NodeType.JOB` and the corresponding ``operation``, ``machine_id``, or ``job_id`` is ``None``, respectively. """__slots__={"node_type":"The type of the node.","_node_id":"Unique identifier for the node.","_operation":("The operation associated with the node."),"_machine_id":("The machine ID associated with the node."),"_job_id":"The job ID associated with the node.",}def__init__(self,node_type:NodeType,operation:Operation|None=None,machine_id:int|None=None,job_id:int|None=None,):ifnode_type==NodeType.OPERATIONandoperationisNone:raiseValidationError("Operation node must have an operation.")ifnode_type==NodeType.MACHINEandmachine_idisNone:raiseValidationError("Machine node must have a machine_id.")ifnode_type==NodeType.JOBandjob_idisNone:raiseValidationError("Job node must have a job_id.")self.node_type:NodeType=node_typeself._node_id:int|None=Noneself._operation=operationself._machine_id=machine_idself._job_id=job_id@propertydefnode_id(self)->int:"""Returns a unique identifier for the node."""ifself._node_idisNone:raiseUninitializedAttributeError("Node has not been assigned an id.")returnself._node_id@node_id.setterdefnode_id(self,value:int)->None:self._node_id=value@propertydefoperation(self)->Operation:"""Returns the operation of the node. This property is mandatory for nodes of type :class:`NodeType.OPERATION`. Raises: UninitializedAttributeError: If the node has no operation. """ifself._operationisNone:raiseUninitializedAttributeError("Node has no operation.")returnself._operation@propertydefmachine_id(self)->int:"""Returns the `machine_id` of the node. This property is mandatory for nodes of type `MACHINE`. Raises: UninitializedAttributeError: If the node has no ``machine_id``. """ifself._machine_idisNone:raiseUninitializedAttributeError("Node has no ``machine_id``.")returnself._machine_id@propertydefjob_id(self)->int:"""Returns the `job_id` of the node. This property is mandatory for nodes of type `JOB`. Raises: UninitializedAttributeError: If the node has no `job_id`. """ifself._job_idisNone:raiseUninitializedAttributeError("Node has no `job_id`.")returnself._job_iddef__hash__(self)->int:returnself.node_iddef__eq__(self,__value:object)->bool:ifisinstance(__value,Node):__value=__value.node_idreturnself.node_id==__valuedef__repr__(self)->str:ifself.node_type==NodeType.OPERATION:return(f"Node(node_type={self.node_type.name}, id={self._node_id}, "f"operation={self.operation})")ifself.node_type==NodeType.MACHINE:return(f"Node(node_type={self.node_type.name}, id={self._node_id}, "f"machine_id={self._machine_id})")ifself.node_type==NodeType.JOB:return(f"Node(node_type={self.node_type.name}, id={self._node_id}, "f"job_id={self._job_id})")returnf"Node(node_type={self.node_type.name}, id={self._node_id})"