# Path: veidt/monte_carlo/base.py
# class State(metaclass=ABCMeta):
#     def __init__(self, state, name=None):
#         """
#         Base class for State.
#         :param state: scalar or iterables
#         :param name: string name
#         """
#         self.state = state
#         self.check_state()
#         self.name = name
#         self.label = name
# 
#     @abstractmethod
#     def change(self):
#         """
#         Change state to new state
#         :return:
#         """
#         pass
# 
#     def check_state(self):
#         """
#         Check if the state make sense, raise Error if not
#         :return:
#         """
#         pass
# 
#     def __eq__(self, other):
#         """
#         Compare two states
#         :param other: other state object
#         :return: bool
#         """
#         if isinstance(self.state, Iterable):
#             return all([i == j for i, j in zip(self.state, other.state)])
#         else:
#             return self.state == other.state
# 
#     def copy(self):
#         """
#         copy a state
#         :return: new state object with same state variable
#         """
#         new_state = self.__class__(copy(self.state), self.name)
# 
#         # copy other attributes
#         # new_state.__dict__.update({i: j for i, j in self.__dict__.items() if i not in ['state', 'name']})
#         return new_state
# 
# class StateStructure(metaclass=ABCMeta):
#     """
#     Structure with StateDict to describe the states
#     Each structure will be associated with a collection of state and can be converted to or from the states
#     """
# 
#     def __init__(self, structure, state_dict):
#         """
# 
#         :param structure: pymatgen structure
#         :param state_dict: StateDict object
#         """
#         self.structure = structure.copy()
#         self.state_dict = state_dict.copy()
# 
#     @abstractmethod
#     def structure_from_states(self, state_dict):
#         """
#         Convert the state into pymatgen structure
#         : param state_dict: StateDict object
#         :return: structure corresponding to the state dictionary
#         """
#         pass
# 
#     @abstractmethod
#     def structure_to_states(self, structure):
#         """
#         Convert structure to corresponding state dictionary
#         :param structure: pymatgen structure
#         :return: state dictionary
#         """
#         pass
# 
#     def to_states(self):
#         """
#         Convert the object to state dictionary
#         :return: StateDict object
#         """
#         return self.structure_to_states(self.structure)
# 
#     def from_states(self, state_dict):
#         """
#         Convert a state dictionary into structure
#         :param state_dict: StateDict object
#         :return:
#         """
#         self.structure = self.structure_from_states(state_dict)
#         self.state_dict = state_dict
# 
#     def change(self):
#         """
#         Perform state changes for all items in the state dictionary and
#         update the structure
#         :return:
#         """
#         [i.change() for i in self.state_dict.values()]
#         self.from_states(self.state_dict)
# 
# class StaticState(State):
#     """
#     StaticState does not change the state when calling the change method
#     """
# 
#     def change(self):
#         pass


import numpy as np
import itertools
from collections import defaultdict
from .base import State, StateStructure, StaticState
    """
    One single variable state, such as temperature, pressure etc
    """

    def check_state(self):
        """
        check if only a scalar value is in the state
        :return:
        """
        if np.size(self.state) > 1:
            raise ValueError("Only single state supported!")
        return


class AtomNumberState(SingleState):
    """
    Number of atom state
    """

    def __init__(self, atom_number, name='atom_number'):
        super(AtomNumberState, self).__init__(atom_number, name)

    def change(self):
        """
        Add or delete one atom
        :return:
        """
        self.state += np.random.choice([1, -1])



# Path: veidt/monte_carlo/base.py
# class State(metaclass=ABCMeta):
#     def __init__(self, state, name=None):
#         """
#         Base class for State.
#         :param state: scalar or iterables
#         :param name: string name
#         """
#         self.state = state
#         self.check_state()
#         self.name = name
#         self.label = name
# 
#     @abstractmethod
#     def change(self):
#         """
#         Change state to new state
#         :return:
#         """
#         pass
# 
#     def check_state(self):
#         """
#         Check if the state make sense, raise Error if not
#         :return:
#         """
#         pass
# 
#     def __eq__(self, other):
#         """
#         Compare two states
#         :param other: other state object
#         :return: bool
#         """
#         if isinstance(self.state, Iterable):
#             return all([i == j for i, j in zip(self.state, other.state)])
#         else:
#             return self.state == other.state
# 
#     def copy(self):
#         """
#         copy a state
#         :return: new state object with same state variable
#         """
#         new_state = self.__class__(copy(self.state), self.name)
# 
#         # copy other attributes
#         # new_state.__dict__.update({i: j for i, j in self.__dict__.items() if i not in ['state', 'name']})
#         return new_state
# 
# class StateStructure(metaclass=ABCMeta):
#     """
#     Structure with StateDict to describe the states
#     Each structure will be associated with a collection of state and can be converted to or from the states
#     """
# 
#     def __init__(self, structure, state_dict):
#         """
# 
#         :param structure: pymatgen structure
#         :param state_dict: StateDict object
#         """
#         self.structure = structure.copy()
#         self.state_dict = state_dict.copy()
# 
#     @abstractmethod
#     def structure_from_states(self, state_dict):
#         """
#         Convert the state into pymatgen structure
#         : param state_dict: StateDict object
#         :return: structure corresponding to the state dictionary
#         """
#         pass
# 
#     @abstractmethod
#     def structure_to_states(self, structure):
#         """
#         Convert structure to corresponding state dictionary
#         :param structure: pymatgen structure
#         :return: state dictionary
#         """
#         pass
# 
#     def to_states(self):
#         """
#         Convert the object to state dictionary
#         :return: StateDict object
#         """
#         return self.structure_to_states(self.structure)
# 
#     def from_states(self, state_dict):
#         """
#         Convert a state dictionary into structure
#         :param state_dict: StateDict object
#         :return:
#         """
#         self.structure = self.structure_from_states(state_dict)
#         self.state_dict = state_dict
# 
#     def change(self):
#         """
#         Perform state changes for all items in the state dictionary and
#         update the structure
#         :return:
#         """
#         [i.change() for i in self.state_dict.values()]
#         self.from_states(self.state_dict)
# 
# class StaticState(State):
#     """
#     StaticState does not change the state when calling the change method
#     """
# 
#     def change(self):
#         pass


# Path: veidt/monte_carlo/state.py
import numpy as np
import itertools
from collections import defaultdict
from .base import State, StateStructure, StaticState

    """
    One single variable state, such as temperature, pressure etc
    """

    def check_state(self):
        """
        check if only a scalar value is in the state
        :return:
        """
        if np.size(self.state) > 1:
            raise ValueError("Only single state supported!")
        return


class AtomNumberState(SingleState):
    """
    Number of atom state
    """

    def __init__(self, atom_number, name='atom_number'):
        super(AtomNumberState, self).__init__(atom_number, name)

    def change(self):
        """
        Add or delete one atom
        :return:
        """
        self.state += np.random.choice([1, -1])



class SpinStructure(StateStructure):