from flask import Flask,jsonify,request
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow

app = Flask(__name__)
app.app_context().push()

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:@localhost/db_dotolist'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

### crear una tabla con el ORM ###
class Tarea(db.Model):
    id = db.Column(db.Integer,primary_key=True) # id INT NOT NULL PRIMARY KEY
    descripcion = db.Column(db.String(200),nullable=False) # descripcion VARCHAR(200) NOT NULL
    estado = db.Column(db.String(100),nullable=False)

    def __init__(self,descripcion,estado):
        self.descripcion = descripcion
        self.estado = estado

### esquemas ###
ma = Marshmallow(app)
class TareaSchema(ma.Schema):
    class Meta:
        fields = ('id','descripcion','estado')

db.create_all()
print("se creo la tabla tarea en la base de datos")

@app.route('/')
def index():
    context = {
        'status':True,
        'content':'servidor activo'
    }

    return jsonify(context)

@app.route('/tarea')
def getTarea():
    data = Tarea.query.all() #select id,descripcion,estado from tarea
    data_schema = TareaSchema(many=True)

    context = {
        'status':True,
        'content':data_schema.dump(data)
    }

    return jsonify(context)

@app.route('/tarea/<id>')
def getTareaById(id):
    data = Tarea.query.get(id)
    data_schema = TareaSchema()

    context = {
        'status':True,
        'content':data_schema.dump(data)
    }

    return jsonify(context)

@app.route('/tarea',methods=['POST'])
def setTarea():
    descripcion = request.json['descripcion']
    estado = request.json['estado']

    #insert into tarea(descripcion,estado) values(?,?)
    nuevaTarea = Tarea(descripcion,estado)
    db.session.add(nuevaTarea)
    db.session.commit()

    data_schema = TareaSchema()

    context = {
        'status':True,
        'content':data_schema.dump(nuevaTarea)
    }

    return jsonify(context)

@app.route('/tarea/<id>',methods=['PUT'])
def updateTarea(id):
    descripcion = request.json['descripcion']
    estado = request.json['estado']

    updateTarea = Tarea.query.get(id)
    updateTarea.descripcion = descripcion
    updateTarea.estado = estado
    db.session.commit()

    data_schema = TareaSchema()

    context = {
        'status':True,
        'content':data_schema.dump(updateTarea)
    }

    return jsonify(context)

@app.route('/tarea/<id>',methods=['DELETE'])
def deleteTarea(id):

    deleteTarea = Tarea.query.get(id)
    db.session.delete(deleteTarea)
    db.session.commit()

    data_schema = TareaSchema()

    context = {
        'status':True,
        'content':data_schema.dump(deleteTarea)
    }

    return jsonify(context)

app.run(debug=True)


import warnings
import copy

from quantum_systems.system_helper import compute_particle_density

class BasisSet:
    """Class serving as a container for matrix elements for various systems. The
    purpose of ``BasisSet`` after a set has been constructed is to be passed to
    a subclass of ``QuantumSystem``. From there on the ``QuantumSystem`` takes
    ownership of the matrix elements and provides methods and functionality to
    be used by second-quantized many-body methods.

    Parameters
    ----------
    l : int
        Number of basis functions.
    dim : int
        Dimensionality of the systems.
    np : module
        Matrix and linear algebra module. Currently only `numpy` is supported.
    includes_spin : bool
        Toggle to determine if the basis set to be created includes explicitly
        in the basis functions. By default we assume that ``BasisSet`` only
        contains spatial orbitals thus there are no explicit spin-dependence in
        the elements.
    anti_symmetrized_u : bool
        Toggle to determine if the two-body matrix elements have been
        anti_symmetrized. By default we assume that this is not the case.
    """

    def __init__(
        self, l, dim, np=None, includes_spin=False, anti_symmetrized_u=False
    ):
        if np is None:
            import numpy as np

        self.np = np

        self.l = l
        self.dim = dim

        self._grid = None

        self._h = None
        self._u = None
        self._s = None
        self._position = None
        self._momentum = None

        self._sigma_x = None
        self._sigma_y = None
        self._sigma_z = None

        self._spin_x = None
        self._spin_y = None
        self._spin_z = None
        self._spin_2 = None
        self._spin_2_tb = None

        self._spf = None
        self._bra_spf = None

        self._nuclear_repulsion_energy = 0
        # We assume negative charge by default, i.e., electrons
        self.particle_charge = -1

        self._includes_spin = includes_spin
        self._anti_symmetrized_u = anti_symmetrized_u

    @property
    def includes_spin(self):
        return self._includes_spin

    @property
    def anti_symmetrized_u(self):
        return self._anti_symmetrized_u

    @property
    def grid(self):
        return self._grid

    @grid.setter
    def grid(self, grid):
        self._grid = grid

    @property
    def h(self):
        return self._h

    @h.setter
    def h(self, h):
        assert all(self.check_axis_lengths(h, self.l))

        self._h = h

    @property
    def u(self):
        return self._u

    @u.setter
    def u(self, u):
        assert all(self.check_axis_lengths(u, self.l))

        self._u = u

    @property
    def s(self):
        return self._s

    @s.setter
    def s(self, s):
        assert all(self.check_axis_lengths(s, self.l))

        self._s = s

    @property
    def position(self):
        return self._position

    @position.setter
    def position(self, position):
        assert len(position) == self.dim

        for i in range(self.dim):
            assert all(self.check_axis_lengths(position[i], self.l))

        self._position = position

    @property
    def dipole_moment(self):
        return self.particle_charge * self.position

    @property
    def momentum(self):
        return self._momentum

    @momentum.setter
    def momentum(self, momentum):
        assert len(momentum) == self.dim

        for i in range(self.dim):
            assert all(self.check_axis_lengths(momentum[i], self.l))

        self._momentum = momentum

    @property
    def spin_x(self):
        return self._spin_x

    @spin_x.setter
    def spin_x(self, spin_x):
        assert self.includes_spin
        assert all(self.check_axis_lengths(spin_x, self.l))

        self._spin_x = spin_x

    @property
    def spin_y(self):
        return self._spin_y

    @spin_y.setter
    def spin_y(self, spin_y):
        assert self.includes_spin
        assert all(self.check_axis_lengths(spin_y, self.l))

        self._spin_y = spin_y

    @property
    def spin_z(self):
        return self._spin_z

    @spin_z.setter
    def spin_z(self, spin_z):
        assert self.includes_spin
        assert all(self.check_axis_lengths(spin_z, self.l))

        self._spin_z = spin_z

    @property
    def spin_2(self):
        return self._spin_2

    @spin_2.setter
    def spin_2(self, spin_2):
        assert self.includes_spin
        assert all(self.check_axis_lengths(spin_2, self.l))

        self._spin_2 = spin_2

    @property
    def spin_2_tb(self):
        return self._spin_2_tb

    @spin_2_tb.setter
    def spin_2_tb(self, spin_2_tb):
        assert self.includes_spin
        assert all(self.check_axis_lengths(spin_2_tb, self.l))

        self._spin_2_tb = spin_2_tb

    @property
    def sigma_x(self):
        return self._sigma_x

    @sigma_x.setter
    def sigma_x(self, sigma_x):
        assert self.includes_spin

        self._sigma_x = sigma_x

    @property
    def sigma_y(self):
        return self._sigma_y

    @sigma_y.setter
    def sigma_y(self, sigma_y):
        assert self.includes_spin

        self._sigma_y = sigma_y

    @property
    def sigma_z(self):
        return self._sigma_z

    @sigma_z.setter
    def sigma_z(self, sigma_z):
        assert self.includes_spin

        self._sigma_z = sigma_z

    @property
    def spf(self):
        return self._spf

    @spf.setter
    def spf(self, spf):
        if not spf is None:
            assert spf.shape[0] == self.l
            assert len((*spf.shape[1:],)) == self.dim

        self._spf = spf

    @property
    def bra_spf(self):
        if self._bra_spf is None and self._spf is not None:
            # Return complex conjugate in case of a Hermitian basis set.
            self._bra_spf = self._spf.conj()

        return self._bra_spf

    @bra_spf.setter
    def bra_spf(self, bra_spf):
        if not bra_spf is None:
            assert bra_spf.shape[0] == self.l
            assert len((*bra_spf.shape[1:],)) == self.dim

        self._bra_spf = bra_spf

    @property
    def nuclear_repulsion_energy(self):
        return self._nuclear_repulsion_energy

    @nuclear_repulsion_energy.setter
    def nuclear_repulsion_energy(self, nuclear_repulsion_energy):
        self._nuclear_repulsion_energy = nuclear_repulsion_energy

    @staticmethod
    def change_arr_module(arr, np):
        return np.asarray(arr) if arr is not None else None

    def change_module(self, np):
        """Function converting all matrix elements to a new module.

        Parameters
        ----------
        np : module
            Array- and linalg-module.
        """
        self.np = np

        for name, arr in [
            ("_h", self.h),
            ("_s", self.s),
            ("_u", self.u),
            ("_spf", self.spf),
            ("_bra_spf", self.bra_spf),
            ("_position", self.position),
            ("_momentum", self.momentum),
            ("_spin_x", self.spin_x),
            ("_spin_y", self.spin_y),
            ("_spin_z", self.spin_z),
            ("_spin_2", self.spin_2),
            ("_spin_2_tb", self.spin_2_tb),
        ]:
            setattr(self, name, self.change_arr_module(arr, self.np))

    def cast_to_complex(self):
        """Function converting all matrix elements to ``np.complex128``, where
        ``np`` is the member array module.
        """
        np = self.np

        for name, arr in [
            ("_h", self.h),
            ("_s", self.s),
            ("_u", self.u),
            ("_spf", self.spf),
            ("_bra_spf", self.bra_spf),
            ("_position", self.position),
            ("_momentum", self.momentum),
            ("_spin_x", self.spin_x),
            ("_spin_y", self.spin_y),
            ("_spin_z", self.spin_z),
            ("_spin_2", self.spin_2),
            ("_spin_2_tb", self.spin_2_tb),
        ]:
            if arr is not None:
                setattr(self, name, arr.astype(np.complex128))

    @staticmethod
    def transform_spf(spf, C, np):
        return np.tensordot(C, spf, axes=((0), (0)))

    @staticmethod
    def transform_bra_spf(bra_spf, C_tilde, np):
        return np.tensordot(C_tilde, bra_spf, axes=((1), (0)))

    @staticmethod
    def transform_one_body_elements(h, C, np, C_tilde=None):
        if C_tilde is None:
            C_tilde = C.conj().T

        return np.dot(C_tilde, np.dot(h, C))

    @staticmethod
    def transform_two_body_elements(u, C, np, C_tilde=None):
        if C_tilde is None:
            C_tilde = C.conj().T

        # abcd, ds -> abcs
        _u = np.tensordot(u, C, axes=(3, 0))
        # abcs, cr -> absr -> abrs
        _u = np.tensordot(_u, C, axes=(2, 0)).transpose(0, 1, 3, 2)
        # abrs, qb -> arsq -> aqrs
        _u = np.tensordot(_u, C_tilde, axes=(1, 1)).transpose(0, 3, 1, 2)
        # pa, aqrs -> pqrs
        _u = np.tensordot(C_tilde, _u, axes=(1, 0))

        return _u

    def get_transformed_h(self, C):
        return self.transform_one_body_elements(self.h, C, np=self.np)

    def get_transformed_u(self, C):
        return self.transform_two_body_elements(self.u, C, np=self.np)

    def _change_basis_one_body_elements(self, C, C_tilde):
        self.h = self.transform_one_body_elements(
            self.h, C, np=self.np, C_tilde=C_tilde
        )

        if self.s is not None:
            self.s = self.transform_one_body_elements(
                self.s, C, C_tilde=C_tilde, np=self.np
            )

        for spin in [self.spin_x, self.spin_y, self.spin_z, self.spin_2]:
            if spin is not None:
                spin = self.transform_one_body_elements(
                    spin, C, C_tilde=C_tilde, np=self.np
                )

    def _change_basis_two_body_elements(self, C, C_tilde):
        self.u = self.transform_two_body_elements(
            self.u, C, np=self.np, C_tilde=C_tilde
        )

        if self.spin_2_tb is not None:
            self.spin_2_tb = self.transform_two_body_elements(
                self.spin_2_tb, C, np=self.np, C_tilde=C_tilde
            )

    def _change_basis_position_elements(self, C, C_tilde):
        position = []

        for i in range(self.position.shape[0]):
            position.append(
                self.transform_one_body_elements(
                    self.position[i], C, np=self.np, C_tilde=C_tilde
                )
            )

        self.position = self.np.asarray(position)

    def _change_basis_momentum_elements(self, C, C_tilde):
        momentum = []

        for i in range(self.momentum.shape[0]):
            momentum.append(
                self.transform_one_body_elements(
                    self.momentum[i], C, np=self.np, C_tilde=C_tilde
                )
            )

        self.momentum = self.np.asarray(momentum)

    def _change_basis_spf(self, C, C_tilde):
        self.bra_spf = self.transform_bra_spf(self.bra_spf, C_tilde, self.np)

        self.spf = self.transform_spf(self.spf, C, self.np)

    def change_basis(self, C, C_tilde=None):
        r"""Function using coefficient matrices to change basis of the matrix
        elements and the single-particle functions. This function also supports
        rectangular coefficient matrices meaning that the number of basis
        functions can be updated. Let :math`\lvert \chi_{\alpha} \rangle`
        (:math:`\langle \tilde{\chi}_{\alpha} \rvert`) be the current basis set
        with :math:`\alpha \in \{1, \dots, N_{\alpha}\}`, and :math:`\lvert
        \phi_p \rangle` (:math:`\langle \tilde{\phi}_p \rvert`)the new basis
        with :math:`p \in \{1, \dots, N_p\}`. Then, for a given coefficient
        matrix :math:`C \in \mathbb{C}^{N_{p}\times N_{\alpha}}`
        (:math:`\tilde{C} \in \mathbb{C}^{N_{\alpha} \times N_p}`) the basis
        change for a single particle state is given by

        .. math:: \lvert \phi_p \rangle = C^{\alpha}_{p}
            \lvert\chi_{\alpha}\rangle,

        where the Einstein summation convention is assumed. Similarly for the
        dual state we have

        .. math:: \langle\tilde{\phi}_p\rvert = \tilde{C}^{p}_{\alpha}
            \langle\tilde{\chi}_{\alpha}\rvert.

        In case of a Hermitian basis we have :math:`\tilde{C} = C^{\dagger}`,
        and the dual states are the Hermitian adjoint of one another.

        Parameters
        ----------
        C : np.ndarray
            Coefficient matrix for "ket"-states.
        C_tilde : np.ndarray
            Coefficient matrix for "bra"-states, by default ``C_tilde`` is
            ``None`` and we treat ``C_tilde`` as the Hermitian conjugate of
            ``C``.
        """
        # Update basis set size
        self.l = C.shape[1]

        # Ensure that C_tilde is not None
        if C_tilde is None:
            C_tilde = C.conj().T

        self._change_basis_one_body_elements(C, C_tilde)
        self._change_basis_two_body_elements(C, C_tilde)

        if self.position is not None:
            self._change_basis_position_elements(C, C_tilde)

        if self.momentum is not None:
            self._change_basis_momentum_elements(C, C_tilde)

        if self.spf is not None:
            self._change_basis_spf(C, C_tilde)

    def compute_particle_density(self, rho_qp, C=None, C_tilde=None):
        r"""Function computing the particle density for a given one-body
        density matrix. This function (optionally) changes the basis of the
        single-particle states for given coefficient matrices. The one-body
        density is given by

        .. math:: \rho(\mathbf{r}) = \tilde{\phi}_{q}(\mathbf{r})
            \rho^{q}_{p} \phi_{p}(\mathbf{r}),

        where :math:`\rho^{q}_{p}` is the one-body density matrix,
        :math:`\phi_p(\mathbf{r})` the spin-orbitals, and
        :math:`\tilde{\phi}_p(\mathbf{r})` the dual spin-orbital.

        Parameters
        ----------
        rho_qp : np.ndarray
            One-body density matrix
        C : np.ndarray
            Coefficient matrix for basis change. Default is ``None`` and hence
            no transformation occurs.
        C_tilde : np.ndarray
            Bra-state coefficient matrix. Default is ``None`` which leads to
            one of two situations. If ``C != None`` ``C_tilde`` is assumed to
            be the conjugated transpose of ``C``. Otherwise, no transformation
            occurs.

        Returns
        -------
        np.ndarray
            Particle density with the same dimensions as the grid.
        """
        assert (
            self._spf is not None
        ), "Set up single-particle functions prior to calling this function"

        ket_spf = self.spf
        bra_spf = self.bra_spf

        if C is not None:
            ket_spf = self.transform_spf(ket_spf, C, self.np)
            C_tilde = C_tilde if C_tilde is not None else C.conj().T
            bra_spf = self.transform_bra_spf(bra_spf, C_tilde, self.np)

        return compute_particle_density(rho_qp, ket_spf, bra_spf, self.np)

    def anti_symmetrize_two_body_elements(self):
        r"""Function making the two-body matrix elements anti-symmetric. This
        corresponds to

        .. math:: \langle \phi_p \phi_q \rvert \hat{u}
            \lvert \phi_r \phi_s \rangle_{AS}
            \equiv
            \langle \phi_p \phi_q \rvert \hat{u} \lvert \phi_r \phi_s \rangle
            -
            \langle \phi_p \phi_q \rvert \hat{u} \lvert \phi_s \phi_r \rangle.
        """
        if not self._anti_symmetrized_u:
            self.u = self.anti_symmetrize_u(self.u)

            if self.spin_2_tb is not None:
                self.spin_2_tb = self.anti_symmetrize_u(self.spin_2_tb)

            self._anti_symmetrized_u = True

    def change_to_general_orbital_basis(
        self, a=[1, 0], b=[0, 1], anti_symmetrize=True
    ):
        r"""Function converting a spatial orbital basis set to a general orbital
        basis. That is, the function duplicates every element by adding a
        spin-function to each spatial orbital. This leads to an
        orbital-restricted spin-orbital where each spatial orbital is included
        in each spin-direction.

        .. math:: \phi_p(\mathbf{r}) \to
            \psi_p(x) = \phi_p(\mathbf{r}) \sigma(m_s),

        where :math:`x = (\mathbf{r}, m_s)` is a generalized coordinate of both
        position :math:`\mathbf{r}` and spin :math:`m_s`. Here
        :math:`\phi_p(\mathbf{r})` is a spatial orbital and :math:`\sigma(m_s)`
        a spin-function with :math:`\sigma \in \{\alpha, \beta\}`. The
        conversion happens in-place.

        Parameters
        ----------
        a : list, np.array
            The :math:`\alpha` (up) spin basis vector. Default is :math:`\alpha
            = (1, 0)^T`.
        b : list, np.array
            The :math:`\beta` (down) spin basis vector. Default is :math:`\beta
            = (0, 1)^T`. Note that ``a`` and ``b`` are assumed orthonormal.
        anti_symmetrize : bool
            Whether or not to anti-symmetrize the elements in the two-body
            Hamiltonian. By default we perform an anti-symmetrization.
        """

        if self._includes_spin:
            warnings.warn(
                "The basis has already been spin-doubled. Avoiding a second "
                + "doubling."
            )
            return

        self._includes_spin = True

        self.l = 2 * self.l

        overlap = self.s.copy()

        self.h = self.add_spin_one_body(self.h, np=self.np)
        self.s = self.add_spin_one_body(self.s, np=self.np)
        self.u = self.add_spin_two_body(self.u, np=self.np)

        # temporary change to allow 2d representations of two-body operators, such as
        # for dvr. A 2d representation is necessary for large basis sets, in which case
        # self.spin_2 also becomes huge. Until a better representation of self.spin_2
        # can be found, we've removed the spin functionality.
        if getattr(self, "u_repr", "4d") != "2d":
            self.a = self.np.array(a).astype(self.np.complex128).reshape(-1, 1)
            self.b = self.np.array(b).astype(self.np.complex128).reshape(-1, 1)

            # Check that spin basis elements are orthonormal
            assert abs(self.np.dot(self.a.conj().T, self.a) - 1) < 1e-12
            assert abs(self.np.dot(self.b.conj().T, self.b) - 1) < 1e-12
            assert abs(self.np.dot(self.a.conj().T, self.b)) < 1e-12

            (
                self.sigma_x,
                self.sigma_y,
                self.sigma_z,
            ) = self.setup_pauli_matrices(self.a, self.b, self.np)

            self.spin_x = 0.5 * self.np.kron(overlap, self.sigma_x)
            self.spin_y = 0.5 * self.np.kron(overlap, self.sigma_y)
            self.spin_z = 0.5 * self.np.kron(overlap, self.sigma_z)

            self.spin_2, self.spin_2_tb = self.setup_spin_squared_operator(
                self.spin_x, self.spin_y, self.spin_z, self.s, self.np
            )

        if anti_symmetrize:
            self.anti_symmetrize_two_body_elements()

        if not self.position is None:
            position = [
                self.add_spin_one_body(self.position[i], np=self.np)
                for i in range(len(self.position))
            ]

            self.position = self.np.array(position)

        if not self.momentum is None:
            momentum = [
                self.add_spin_one_body(self.momentum[i], np=self.np)
                for i in range(len(self.momentum))
            ]

            self.momentum = self.np.array(momentum)

        if not self.spf is None:
            self.spf = self.add_spin_spf(self.spf, self.np)

            # Make sure that we check if _bra_spf is not None, otherwise we
            # potentially construct the dual state.
            if not self._bra_spf is None:
                self.bra_spf = self.add_spin_bra_spf(self._bra_spf, self.np)

        # Due to inherently complex matrices for spin we cast all elements to
        # complex numbers.
        self.cast_to_complex()

        return self

    @staticmethod
    def setup_pauli_matrices(a, b, np):
        r"""Static method computing matrix elements of the Pauli spin-matrices
        in a given orthonormal basis of spin functions :math:`\{\alpha,
        \beta\}`.

        .. math:: (\sigma_i)^{\rho}_{\gamma}
            = \langle \rho \rvert \hat{\sigma}_i \lvert \gamma \rangle,

        where :math:`\rho, \gamma \in \{\alpha, \beta\}` and :math:`i \in \{x,
        y, z\}` for the three Pauli matrices.

        Parameters
        ----------
        a : np.ndarray
            The :math:`\alpha` basis vector as a column vector.
        b : np.ndarray
            The :math:`\beta` basis vector as a column vector. Note that the
            two basis vectors are assumed to be orthonormal.
        np : module
            An appropriate array and linalg module.

        Returns
        -------
        tuple
            The three Pauli matrices in the order :math:`\sigma_x, \sigma_y,
            \sigma_z`.

        Example
        -------

        >>> import numpy as np
        >>> a = np.array([1, 0]).reshape(-1, 1)
        >>> b = np.array([0, 1]).reshape(-1, 1)
        >>> sigma_x, sigma_y, sigma_z = BasisSet.setup_pauli_matrices(a, b, np)
        >>> print(sigma_x)
        [[0.+0.j 1.+0.j]
         [1.+0.j 0.+0.j]]
        >>> print(sigma_y)
        [[0.+0.j 0.-1.j]
         [0.+1.j 0.+0.j]]
        >>> print(sigma_z)
        [[ 1.+0.j  0.+0.j]
         [ 0.+0.j -1.+0.j]]
        """
        sigma_x_mat = np.array([[0, 1], [1, 0]]).astype(np.complex128)
        sigma_y_mat = np.array([[0, -1j], [1j, 0]])
        sigma_z_mat = np.array([[1, 0], [0, -1]]).astype(np.complex128)

        sigma_x = np.zeros_like(sigma_x_mat)
        sigma_y = np.zeros_like(sigma_y_mat)
        sigma_z = np.zeros_like(sigma_z_mat)

        for i, s in enumerate([a, b]):
            for j, t in enumerate([a, b]):
                sigma_x[i, j] = np.dot(s.conj().T, np.dot(sigma_x_mat, t))
                sigma_y[i, j] = np.dot(s.conj().T, np.dot(sigma_y_mat, t))
                sigma_z[i, j] = np.dot(s.conj().T, np.dot(sigma_z_mat, t))

        return sigma_x, sigma_y, sigma_z

    @staticmethod
    def setup_spin_squared_operator(spin_x, spin_y, spin_z, overlap, np):
        r"""Static method computing the matrix elements of the one- and
        two-body spin squared operator, :math:`\hat{S}^2`. The operator is
        computed by

        .. math:: \hat{S}^2 = \hat{S}_x^2 + \hat{S}_y^2 + \hat{S}_z^2,

        where each squared direction :math:`\hat{S}_i^2` can be written

        .. math:: \hat{S}_i^2
            = (S_i)^{p}_{r} (S_i)^{r}_{q}
            \hat{c}^{\dagger}_{p} \hat{c}_{q}
            + (S_i)^{p}_{r} (S_i)^{q}_{s}
            \hat{c}^{\dagger}_{p} \hat{c}^{\dagger}_{q}
            \hat{c}_{s} \hat{c}_{r},

        in the second quantization formulation.

        Parameters
        ----------
        spin_x : np.ndarray
            Spin-matrix in :math:`x`-direction including orbital overlap.
        spin_y : np.ndarray
            Spin-matrix in :math:`y`-direction including orbital overlap.
        spin_z : np.ndarray
            Spin-matrix in :math:`z`-direction including orbital overlap.
        overlap : np.ndarray
            The overlap matrix elements between the spin-orbitals.
        np : module
            An appropriate array and linalg module.

        Returns
        -------
        (np.ndarray, np.ndarray)
            The spin-squared operator as two arrays on the form ``(l, l)`` and
            ``(l, l, l, l)``, where ``l`` is the number of spin-orbitals. The
            former corresponds to the one-body part of the spin-squared
            operator whereas the latter is the two-body part.
        """

        l = len(spin_x)

        spin_2 = np.zeros_like(spin_x)
        spin_2_tb = np.zeros((l, l, l, l), dtype=spin_2.dtype)

        for s_i in [spin_x, spin_y, spin_z]:
            spin_2 += s_i @ overlap @ s_i
            spin_2_tb += np.einsum("pr, qs -> pqrs", s_i, s_i)

        return spin_2, spin_2_tb

    @staticmethod
    def add_spin_spf(spf, np):
        new_shape = [spf.shape[0] * 2, *spf.shape[1:]]
        new_spf = np.zeros(tuple(new_shape), dtype=spf.dtype)

        new_spf[::2] = spf
        new_spf[1::2] = spf

        return new_spf

    @staticmethod
    def add_spin_bra_spf(bra_spf, np):
        if bra_spf is None:
            return None

        return BasisSet.add_spin_spf(bra_spf, np)

    @staticmethod
    def add_spin_one_body(h, np):
        return np.kron(h, np.eye(2))

    @staticmethod
    def add_spin_two_body(_u, np):
        return np.kron(_u, np.einsum("pr, qs -> pqrs", np.eye(2), np.eye(2)))

    @staticmethod
    def anti_symmetrize_u(_u):
        return _u - _u.transpose(0, 1, 3, 2)

    @staticmethod
    def check_axis_lengths(arr, length):
        return [length == axis for axis in arr.shape]

    def copy_basis(self):
        """Function creating a deep copy of the current basis. This function
        is a hack as we have to temporarily remove the stored module before
        using Python's ``copy.deepcopy``-function.

        Returns
        -------
        BasisSet
            A deep copy of the current basis.
        """

        np = self.np
        self.np = None

        new_basis = copy.deepcopy(self)

        new_basis.change_module(np)
        self.change_module(np)

        assert self.np is np

        return new_basis


from datetime import datetime
from collections import defaultdict
from typing import Optional

from consts import *
import utils

class Node:

    def __init__(self, data: defaultdict[str], next = None, prev = None):
        self.data = data
        self.next = next
        self.prev = prev

class MessageQueue:

    def __init__(self):
        head_data, tail_data = defaultdict(str), defaultdict(str)
        head_data["dummy"], tail_data["dummy"] = "head", "tail"
        self.head, self.tail = Node(head_data), Node(tail_data)
        self.head.next, self.tail.prev = self.tail, self.head
        self.size = 0
        self.make_queue()

    def make_queue(self):
        for data in utils.get_data_from_json(MESSAGES_DATA_PATH):
            node = Node(data)
            self._add(node)

    def get_front(self) -> Optional[Node]:
        if not self.size:
            return None

        return self.head.next

    def get_last(self) -> Optional[Node]:
        if not self.size:
            return None

        return self.tail.prev

    def enqueue(self, data: defaultdict[str]) -> None:
        self._add(Node(data))

    def dequeue(self) -> None:
        if not self.size:
            return None

        self._remove(self.head.next)

    def update(self) -> None:
        data_list = []
        # data_list = [data for data in utils.get_data_from_json(MESSAGES_DATA_PATH)]
        cur = self.head.next
        while cur != self.tail:
            data_list.append(cur.data)
            cur = cur.next

        utils.write_data_to_json(data_list, MESSAGES_DATA_PATH)

    def _add(self, node: Node) -> None:
        prev_node = self.tail.prev
        node.next, node.prev = self.tail, prev_node
        self.tail.prev, prev_node.next = node, node
        self.size += 1

    def _remove(self, node: Node):
        prev, nxt = node.prev, node.next
        prev.next, nxt.prev = nxt, prev
        self.size -= 1

def add_message(messages: MessageQueue, account_number: str) -> MessageQueue:
    print("We are very appreciated to hear from your thinking, your satisfied, dis-satisfied, "
          "and the idea to help us improve!!!")
    print(f"Your message should be less than {MESSAGE_MAX_CHARACTERS} characters and "
          f"less than {MESSAGE_MAX_WORDS} words")
    failed_attempt = FAILED_ATTEMPT
    message = ""
    while failed_attempt:
        message = input("Please give a message here: ")
        if not utils.is_valid_message(message):
            failed_attempt -= 1
            print("Your message is too long, please try a shorter one!!!")
            print("You have %d try left!!!" % failed_attempt)
        else:
            break

    if not failed_attempt:
        print("You send invalid message many times, please wait a few minutes to try it again!!!")
        return messages

    time_now = datetime.now()
    timestamp = datetime.timestamp(time_now)
    message_data = defaultdict(str)
    message_data[ACCOUNT_NUMBER] = account_number
    message_data[MESSAGE] = message
    message_data[TIMESTAMP] = str(timestamp)
    message_data[TIME] = str(time_now)
    print(message_data)

    messages.enqueue(message_data)

    return messages

def read_message(messages: MessageQueue) -> Optional[MessageQueue]:
    print("Let's see the users' feedback to improve our application")
    if not messages.size:
        print("There are no messages to read")
        utils.proceed_next()
        return messages

    message_data = messages.get_front().data

    messages.dequeue()
    print(f"Messages from user: {message_data[ACCOUNT_NUMBER]}")
    utils.proceed_next()
    print(f"Time message sent: {message_data[TIME]}")
    utils.proceed_next()
    print(f"Message: {message_data[MESSAGE]}")
    utils.proceed_next()
    print(message_data)
    utils.proceed_next()

    return messages


import typer

from pm.database.services import (add_program, get_all_projects, get_program,
                                  get_program_id, get_programs_id,
                                  show_all_programs)

app = typer.Typer()
project_app = typer.Typer()
app.add_typer(project_app, name='project')
program_app = typer.Typer()
app.add_typer(program_app, name='manage')

@project_app.command(name='ls')
def project_ls():
    print("Following projects are in the database:")
    all_p = get_all_projects()
    for p in all_p:
        print(p.name)

@program_app.command(name='add')
def program_add(program_name: str, path: str):
    add_program(program_name, path)
    print(f"Added program {program_name} to database! Hurray!")

@program_app.command(name='delete')
def program_delete(program_name: str):
    program_id = get_programs_id(program_name)
    print(f"Deleted program {program_name} from database! Hurray!")

@program_app.command(name='get')
def program_get(program_name: str):
    program_id = get_program_id(program_name)
    program = get_program(program_id)
    if program:
        print(f"There is a program by the name of {program_id.name}")
    print("No such program in the database")

@program_app.command(name='ls')
def program_ls():
    print("Following programs are installed in the database:")
    all_p = show_all_programs()
    for p in all_p:
        print(p.name)


from absl import logging
from contextlib import nullcontext
import os
from typing import List

import tensorflow as tf
from tensorflow.python.framework import ops

from monolith.native_training import basic_restore_hook
from monolith.native_training import save_utils
from monolith.native_training import utils
from monolith.native_training.runtime.ops import gen_monolith_ops
from monolith.utils import get_libops_path
from monolith.native_training.model_export.export_context import is_exporting_standalone

HASH_FILTER_CAPACITY = 300000000
HASH_FILTER_SPLIT_NUM = 7

filter_ops = gen_monolith_ops

filter_save_op = gen_monolith_ops

filter_restore_op = gen_monolith_ops

_TIMEOUT_IN_MS = 30 * 60 * 1000

class FilterType(object):

  SLIDING_HASH_FILTER = 'sliding_hash_filter'
  PROBABILISTIC_FILTER = 'probabilistic_filter'
  NO_FILTER = 'no_filter'

def create_hash_filter(capacity: int,
                       split_num: int,
                       config: bytes = b"",
                       name_suffix: str = "") -> tf.Tensor:
  """Creates a hash filter"""
  return filter_ops.MonolithHashFilter(capacity=capacity,
                                       split_num=split_num,
                                       config=config,
                                       shared_name="MonolithHashFilter" +
                                       name_suffix)

def create_probabilistic_filter(equal_probability,
                                config: bytes = b"",
                                name_suffix: str = "") -> tf.Tensor:
  """Creates a probabilistic filter"""
  return filter_ops.MonolithProbabilisticFilter(
      equal_probability=equal_probability,
      config=config,
      shared_name="MonolithProbabilisticFilter" + name_suffix)

def create_dummy_hash_filter(name_suffix: str = "0") -> tf.Tensor:
  """Creates a dummy hash filter"""
  return filter_ops.MonolithDummyHashFilter(shared_name="DummyHashFilter" +
                                            name_suffix)

def _create_hash_filter(
    enable_hash_filter: bool,
    config: bytes = b"",
    name_suffix: str = "",
    filter_capacity: int = HASH_FILTER_CAPACITY,
    filter_split_num: int = HASH_FILTER_SPLIT_NUM,
    filter_equal_probability: bool = False,
    filter_type: FilterType = FilterType.SLIDING_HASH_FILTER) -> tf.Tensor:
  if enable_hash_filter is True:
    if filter_type == FilterType.SLIDING_HASH_FILTER:
      return create_hash_filter(filter_capacity, filter_split_num, config,
                                name_suffix)
    elif filter_type == FilterType.PROBABILISTIC_FILTER:
      return create_probabilistic_filter(filter_equal_probability, config,
                                         name_suffix)
    elif filter_type == FilterType.NO_FILTER:
      return create_dummy_hash_filter(name_suffix)
    else:
      raise ValueError("Invalid filter type, please investigate and retry!")
  else:
    return create_dummy_hash_filter(name_suffix)

def create_hash_filters(
    ps_num: int,
    enable_hash_filter: bool,
    config: bytes = b"",
    filter_capacity: int = HASH_FILTER_CAPACITY,
    filter_split_num: int = HASH_FILTER_SPLIT_NUM,
    filter_equal_probability: bool = False,
    filter_type: FilterType = FilterType.SLIDING_HASH_FILTER
) -> List[tf.Tensor]:
  logging.info(
      "Create hash fitlers, enable_hash_filter:{}.".format(enable_hash_filter))
  if ps_num == 0:
    return [
        _create_hash_filter(enable_hash_filter,
                            config,
                            "",
                            filter_capacity,
                            filter_split_num,
                            filter_equal_probability=filter_equal_probability,
                            filter_type=filter_type)
    ]
  else:
    hash_filters = []
    for i in range(ps_num):
      ps_device_name = utils.ps_device(i)
      with nullcontext() if is_exporting_standalone() else tf.device(
          ps_device_name):
        hash_filters.append(
            _create_hash_filter(
                enable_hash_filter,
                config,
                "_" + str(i),
                filter_capacity,
                filter_split_num,
                filter_equal_probability=filter_equal_probability,
                filter_type=filter_type))
    return hash_filters

def save_hash_filter(hash_filter: tf.Tensor,
                     hash_filter_basename: tf.Tensor,
                     enable_hash_filter: bool = False) -> tf.Operation:
  if enable_hash_filter is True:
    return filter_save_op.monolith_hash_filter_save(hash_filter,
                                                    hash_filter_basename)
  else:
    return tf.no_op()

def restore_hash_filter(hash_filter: tf.Tensor,
                        hash_filter_base_name: tf.Tensor,
                        enable_hash_filter: bool = False) -> tf.Operation:
  if enable_hash_filter is True:
    return filter_restore_op.monolith_hash_filter_restore(
        hash_filter, hash_filter_base_name)
  else:
    return tf.no_op()

def intercept_gradient(filter_tensor: tf.Tensor, ids: tf.Tensor,
                       embeddings: tf.Tensor):
  """
  If id is supposed to be filtered, the gradient will be intercepted. Output the same
  embeddings.
  Args:
    ids - a 1-D int64 tensor.
    embeddings - a N-d embedding tensor whose the first dimension is corresponding to ids.
  """
  return filter_ops.MonolithHashFilterInterceptGradient(
      filter_handle=filter_tensor, ids=ids, embeddings=embeddings)

class HashFilterCheckpointSaverListener(tf.estimator.CheckpointSaverListener):
  """
  Saves the hash filters when saver is run.
  """

  def __init__(self,
               basename: str,
               hash_filters: [tf.Tensor],
               enable_hash_filter: bool = False,
               enable_save_restore: bool = True):
    """
    |basename| should be a file name which is same as what is passed to saver.
    |hash_filters| hash filters to save in checkpoint.
    |enable_hash_filter| whether use real hash filters. If true, will save
                         hash filters in checkpoint. If false, will skip save
                         logic internally.
    enable_hash_filter: TODO(zouxuan) Whether to use save and restore on the
                        hash filter.
                        Hash filter is broken for save restore during sync
                        training right now.
    """
    super().__init__()
    self._helper = save_utils.SaveHelper(basename)
    self._hash_filters = hash_filters
    self._enable_hash_filter = enable_hash_filter
    self._enable_save_restore = enable_save_restore
    self._hash_filter_id_to_placeholder = {}
    self._save_op = self._build_save_graph()

  def before_save(self, sess, global_step_value):
    """
    We use before save so the checkpoint file is updated after we successfully
    save the hash filter.
    """
    if self._enable_hash_filter is False or self._enable_save_restore is False:
      return

    feed_dict = {}
    hash_filter_names = []
    asset_dir = self._helper.get_ckpt_asset_dir(
        self._helper.get_ckpt_prefix(global_step_value))
    tf.io.gfile.makedirs(asset_dir)
    for ps_idx, hash_filter in enumerate(self._hash_filters):
      hash_filter_basename = asset_dir + "hash_filter_{}".format(ps_idx)
      hash_filter_names.append(hash_filter_basename)
      feed_dict.update({
          self._hash_filter_id_to_placeholder[id(hash_filter)]:
              hash_filter_basename
      })

    sess.run(self._save_op,
             feed_dict=feed_dict,
             options=tf.compat.v1.RunOptions(timeout_in_ms=_TIMEOUT_IN_MS))
    logging.info("Finished saving hash filters.")

  def _build_save_graph(self) -> tf.Operation:
    if self._enable_hash_filter is False or self._enable_save_restore is False:
      return tf.no_op()

    last_op = tf.no_op()
    for ps_idx, hash_filter in enumerate(self._hash_filters):
      hash_filter_basename = tf.compat.v1.placeholder(tf.string, shape=[])
      self._hash_filter_id_to_placeholder.update(
          {id(hash_filter): hash_filter_basename})
      with tf.control_dependencies([last_op]):
        last_op = save_hash_filter(hash_filter, hash_filter_basename, True)
    return last_op

class HashFilterCheckpointRestorerListener(
    basic_restore_hook.CheckpointRestorerListener):
  """Restores the hash filters from basename"""

  def __init__(self,
               basename: str,
               hash_filters: [tf.Tensor],
               enable_hash_filter: bool = False,
               enable_save_restore: bool = True):
    """
    |basename| should be a file name which is same as what is passed to saver.
    |hash_filters| hash filters to save in checkpoint.
    |enable_hash_filter| whether use real hash filters. If true, will save
                         hash filters in checkpoint. If false, will skip save
                         logic internally.
    enable_hash_filter: TODO(zouxuan) Whether to use save and restore on the
                        hash filter.
                        Hash filter is broken for save restore during sync
                        training right now.
    """
    super().__init__()
    self._basename = basename
    self._helper = save_utils.SaveHelper(self._basename)
    self._hash_filters = hash_filters
    self._enable_hash_filter = enable_hash_filter
    self._enable_save_restore = enable_save_restore
    self._hash_filter_id_to_placeholder = {}
    self._restore_op = self._build_restore_graph()

  def before_restore(self, session):
    """
    We use before restore so as to strictly control the order of restorer listeners.

    """
    ckpt_prefix = tf.train.latest_checkpoint(os.path.dirname(self._basename))
    if not ckpt_prefix:
      logging.info("No checkpoint found in %s. Skip the hash filters restore.",
                   self._basename)
      return
    logging.info("Restore hash filter from %s", ckpt_prefix)
    asset_dir = self._helper.get_ckpt_asset_dir(ckpt_prefix)
    if tf.io.gfile.exists(asset_dir):
      self._restore_from_path_prefix(session, asset_dir)
    else:
      # This is the legacy behavior and should be removed soon.
      self._restore_from_path_prefix(session, ckpt_prefix)

  def _restore_from_path_prefix(self, sess, path_prefix):
    if self._enable_hash_filter is False or self._enable_save_restore is False:
      return

    feed_dict = {}
    hash_filter_names = []
    for ps_idx, hash_filter in enumerate(self._hash_filters):
      hash_filter_basename = path_prefix + "hash_filter_{}".format(ps_idx)
      hash_filter_names.append(hash_filter_basename)
      feed_dict.update({
          self._hash_filter_id_to_placeholder[id(hash_filter)]:
              hash_filter_basename
      })

    sess.run(self._restore_op,
             feed_dict=feed_dict,
             options=tf.compat.v1.RunOptions(timeout_in_ms=_TIMEOUT_IN_MS))

  def _build_restore_graph(self) -> tf.Operation:
    if self._enable_hash_filter is False or self._enable_save_restore is False:
      return tf.no_op()

    restore_ops = []
    for ps_idx, hash_filter in enumerate(self._hash_filters):
      hash_filter_basename = tf.compat.v1.placeholder(tf.string, shape=[])
      self._hash_filter_id_to_placeholder.update(
          {id(hash_filter): hash_filter_basename})
      restore_ops.append(
          restore_hash_filter(hash_filter, hash_filter_basename, True))
    return tf.group(restore_ops)

@ops.RegisterGradient("MonolithHashFilterInterceptGradient")
def _intercept_gradient_gradient(op: tf.Operation, grad: tf.Tensor):
  filter_tensor = op.inputs[0]
  ids = op.inputs[1]
  filtered_grad = filter_ops.MonolithHashFilterInterceptGradientGradient(
      filter_handle=filter_tensor, ids=ids, grad=grad)
  return None, None, filtered_grad


import os
import sys

import torch
import numpy as np
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision.transforms import transforms
import matplotlib.pyplot as plt
from pytorch.pair_dataset import PairDataset

module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
    sys.path.append(module_path)

class Siamese_V2(nn.Module):
    def __init__(self):
        super(Siamese_V2, self).__init__()
        self.cnn = nn.Sequential(
            nn.Conv2d(3, 64, 10, stride=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 128, 7, stride=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(128, 128, 4, stride=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, 2),
            nn.Conv2d(128, 256, 4, stride=1),
            nn.ReLU(inplace=True),

        )
        self.out = nn.Sequential(
            nn.Linear(47616, 500),
            nn.Sigmoid()
        )
    def forward(self, x, y):
        x = self.cnn(x)
        x = x.view(x.shape[0], -1)
        x = self.out(x)

        y = self.cnn(y)
        y = y.view(y.shape[0], -1)
        y = self.out(y)

        return x, y

class ContrastiveLoss(torch.nn.Module):
    """
    Contrastive loss function.
    Based on: http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
    """

    def __init__(self, margin=2.0):
        super(ContrastiveLoss, self).__init__()
        self.margin = margin

    def forward(self, output1, output2, label):
        euclidean_distance = torch.nn.functional.pairwise_distance(output1, output2)
        loss_contrastive = torch.mean((1 - label) * torch.pow(euclidean_distance, 2) +
                                      (label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))

        return loss_contrastive

def test(net, test_loader):
    criterion = ContrastiveLoss()
    for batch_idx, (imgs, target) in enumerate(test_loader):
        for i in range(len(imgs)):
            imgs[i] = Variable(imgs[i].cuda())

        p1, p2 = imgs[0], imgs[1]
        target = target.squeeze(0).type(torch.FloatTensor).cuda()
        output1, output2 = net.forward(p1, p2)
        loss = criterion(output1, output2, target)

        print("here")
        right = len((torch.round_(loss) == target).nonzero())
        acc = right / len(p1)
        print("acc {}".format(acc))

        break

def train(net, data_loader, number_epoch, lr, test_loader = None ,cuda=True):
    net.train()
    optimizer = optim.Adam(net.parameters(), lr=lr)
    loss_history = []
    criterion = ContrastiveLoss()

    if cuda:
        net.cuda()

    for epoch in range(number_epoch):
        for batch_idx, (imgs, target) in enumerate(data_loader):

            if cuda:
                for i in range(len(imgs)):
                    imgs[i] = Variable(imgs[i].cuda())

            p1, p2 = imgs[0], imgs[1]
            target = target.squeeze(0).type(torch.FloatTensor).cuda()

            optimizer.zero_grad()  # zero the gradient buffers
            output1, output2 = net.forward(p1, p2)
            loss = criterion(output1, output2, target)

            loss.backward()
            optimizer.step()  # Does the update

            if batch_idx % 20 == 19:
                print("batch_idx", batch_idx)
                print("Epoch number {}\n Current loss {}\n".format(epoch, loss.item()))
                loss_history.append(loss.item())

            if batch_idx % 30 == 29:
                test(net, test_loader)

            if batch_idx % 100 == 99:
                break

    torch.save(net.state_dict(), '../reId/siamese_triplet.pth')

    plt.plot(loss_history)
    plt.title('Loss')
    plt.show()

if __name__ == "__main__":
    path = '../dataset/re-id/campus/*'

    # create transform
    transform = transforms.Compose([
        transforms.Resize((160, 60)),
        transforms.RandomHorizontalFlip(),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    batch_size = 2
    train_dataset = PairDataset(path, mode="train", transform=transform)
    train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)

    test_dataset = PairDataset(path, mode="test", transform=transform)
    test_loader = DataLoader(test_dataset, batch_size=12, shuffle=True)
    net = Siamese_V2()
    train(net, train_loader, 1, 0.05, test_loader=test_loader, cuda=True)


import test.bootstrap
import ifcopenshell.api

class TestEditQto(test.bootstrap.IFC4):
    def test_editing_a_blank_buildingsmart_templated_qto(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Qto_WallBaseQuantities")
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={"Length": 1, "NetSideArea": 2, "NetVolume": 3},
        )
        pset = element.IsDefinedBy[0].RelatingPropertyDefinition

        assert pset.Quantities[0].Name == "Length"
        assert pset.Quantities[0].LengthValue == 1

        assert pset.Quantities[1].Name == "NetSideArea"
        assert pset.Quantities[1].AreaValue == 2

        assert pset.Quantities[2].Name == "NetVolume"
        assert pset.Quantities[2].VolumeValue == 3

    def test_editing_an_existing_buildingsmart_templated_pset(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Qto_WallBaseQuantities")
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={"Length": 1, "NetSideArea": 2, "NetVolume": 3},
        )
        ifcopenshell.api.run("pset.edit_qto", self.file, qto=qto, properties={"Length": 42, "NetSideArea": None})
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition

        assert qto.Quantities[0].Name == "Length"
        assert qto.Quantities[0].LengthValue == 42

        assert qto.Quantities[1].Name == "NetVolume"
        assert qto.Quantities[1].VolumeValue == 3

        assert len(qto.Quantities) == 2

    def test_not_adding_a_property_if_it_is_none(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Qto_WallBaseQuantities")
        ifcopenshell.api.run("pset.edit_qto", self.file, qto=qto, properties={"Length": None})
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition
        assert len(qto.Quantities) == 0

    def test_editing_a_qto_name(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="foo")
        ifcopenshell.api.run("pset.edit_qto", self.file, qto=qto, name="bar")
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition
        assert qto.Name == "bar"

    def test_adding_quantities_without_a_template_with_autodetected_and_manual_data_types(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Foo_Bar")
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={
                "MyArea": self.file.createIfcAreaMeasure(1),
                "MyCount": self.file.createIfcCountMeasure(2),
                "MyLength": self.file.createIfcLengthMeasure(3),
                "MyTime": self.file.createIfcTimeMeasure(5),
                "MyVolume": self.file.createIfcVolumeMeasure(6),
                "MyWeight": self.file.createIfcMassMeasure(7),
            },
        )
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition

        assert qto.Quantities[0].Name == "MyArea"
        assert qto.Quantities[0].AreaValue == 1

        assert qto.Quantities[1].Name == "MyCount"
        assert qto.Quantities[1].CountValue == 2

        assert qto.Quantities[2].Name == "MyLength"
        assert qto.Quantities[2].LengthValue == 3

        assert qto.Quantities[3].Name == "MyTime"
        assert qto.Quantities[3].TimeValue == 5

        assert qto.Quantities[4].Name == "MyVolume"
        assert qto.Quantities[4].VolumeValue == 6

        assert qto.Quantities[5].Name == "MyWeight"
        assert qto.Quantities[5].WeightValue == 7

    def test_editing_quantities_with_autodetected_existing_types(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Foo_Bar")
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={
                "MyLength": self.file.createIfcLengthMeasure(12),
            },
        )
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={
                "MyLength": 34,
            },
        )
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition
        assert qto.Quantities[0].Name == "MyLength"
        assert qto.Quantities[0].LengthValue == 34

    def test_editing_properties_with_an_explicit_type(self):
        element = ifcopenshell.api.run("root.create_entity", self.file, ifc_class="IfcWall")
        qto = ifcopenshell.api.run("pset.add_qto", self.file, product=element, name="Foo_Bar")
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={
                "MyLength": self.file.createIfcLengthMeasure(12),
            },
        )
        ifcopenshell.api.run(
            "pset.edit_qto",
            self.file,
            qto=qto,
            properties={
                "MyLength": self.file.createIfcAreaMeasure(34),
            },
        )
        qto = element.IsDefinedBy[0].RelatingPropertyDefinition
        assert qto.Quantities[0].Name == "MyLength"
        assert qto.Quantities[0].LengthValue == 34


from BitstringOperations import BitStringOperations

class Preprocessor:

	"""
	Description:

		Splits a string into a list of strings with a size of 512 bits.

	Functions:

		preproces(string) -> [strings]

	"""

	@staticmethod
	def preprocess(string):
		"""Splits the string into 512 bit sections by adding padding if length is not a multiple of 512 and adds the length of the message in bits to the end."""

		string = BitStringOperations.joinBits(string)
		loM = BitStringOperations.lengthOfMessageBits(len(string))

		string +="1"

		while ((len(string) + 64) % 512 != 0):
			string += "0"

		string += loM

		chunks = [string[i:i+512] for i in range(0, len(string), 512)]

		return chunks


import numpy as np
import re

def get_equation_sides(raw_inp):
    raw_inp = raw_inp.replace(" ", "")
    return re.split(r"->|=", raw_inp)

def get_equation_terms(side):
    return re.findall(r"(?:\(?[A-Z][a-z]*\d*\)?\d*)+", side)

def get_matrix_equation(terms_1, terms_2):
    dim = len(terms_2) + len(terms_1) - 1
    matrix = np.zeros((dim, dim))
    vector = np.zeros(dim)

    elements = {}
    for col, term in enumerate(terms_1):
        segments = re.findall(r"([A-Z][a-z]*)(\d*)", term)
        for segment in segments:
            element, number = segment
            if element not in elements:
                if len(elements) == 0:
                    elements[element] = 0
                else:
                    elements[element] = max(elements.values()) + 1
            row = elements[element]

            if number == "":
                number = 1
            else:
                number = int(number)
            matrix[row][col] = number

    for col, term in enumerate(terms_2[:-1]):
        segments = re.findall(r"([A-Z][a-z]*)(\d*)", term)
        for segment in segments:
            element, number = segment
            if element not in elements:
                if len(elements) == 0:
                    elements[element] = 0
                else:
                    elements[element] = max(elements.values()) + 1
            row = elements[element]

            if number == "":
                number = -1
            else:
                number = -int(number)
            matrix[row][col + len(terms_1)] = number

    term = terms_2[-1]
    segments = re.findall(r"([A-Z][a-z]*)(\d*)", term)
    for segment in segments:
        element, number = segment
        if element not in elements:
            if len(elements) == 0:
                elements[element] = 0
            else:
                elements[element] = max(elements.values()) + 1
        row = elements[element]

        if number == "":
            number = 1
        else:
            number = int(number)
        vector[row] = number
    return matrix, vector

def solve_matrix_equation(matrix, vector):
    try:
        inverse = np.linalg.inv(matrix)
    except np.linalg.LinAlgError:
        print("Equation Can not be Balanced")
        return
    coefficients = np.matmul(inverse, vector.transpose())
    coefficients = np.append(coefficients, 1)
    return coefficients

def simplify_coefficients(coefficients):
    if 0 not in coefficients:
        coefficients /= np.min(coefficients)
        coefficients = np.round(coefficients).astype(int)
    else:
        return

    return coefficients

def display_balanced_equation(coefficients, l_terms, r_terms):
    new_l_terms = []
    new_r_terms = []
    for i, term in enumerate(l_terms):
        c = coefficients[i]
        str_c = str(abs(c)) if abs(c) != 1 else ""

        if c > 0:
            new_l_terms.append((str_c, term))
        else:
            new_r_terms.append((str_c, term))

    for i, term in enumerate(r_terms):
        c = coefficients[i + len(l_terms)]
        str_c = str(abs(c)) if abs(c) not in [0, 1] else ""
        if c > 0:
            new_r_terms.append((str_c, term))
        else:
            new_l_terms.append((str_c, term))

    output = ' + '.join([''.join(term) for term in new_l_terms]) + \
             " -> " + \
             ' + '.join([''.join(term) for term in new_r_terms])
    return output

def main():
    # inp = input("Enter a Chemical Equation to Balance (Separate Sides With '=' or '->'): \n")
    inp = "He + O2->2He2O"
    l_side, r_side = get_equation_sides(inp)
    l_terms = get_equation_terms(l_side)
    r_terms = get_equation_terms(r_side)

    matrix, vector = get_matrix_equation(l_terms, r_terms)
    coefficients = solve_matrix_equation(matrix, vector)
    if coefficients is None:
        return

    coefficients = simplify_coefficients(coefficients)
    if coefficients is not None:
        print(display_balanced_equation(coefficients, l_terms, r_terms))
    else:
        print("Equation Can not be Balanced")
        return

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from decimal import *

def add_conversion_factors(apps, schema_editor):
	Product = apps.get_model("nutrient", "Product")

	product_info = [
		("Beef", Decimal(3.99), "1 lbs"),
		("Eggs", Decimal(4.69), "18 Eggs"),
		("Chicken Breast", Decimal(5.49), "1 lbs"),
		("Bacon", Decimal(6.99), "1 lbs"),
		("Asparagus", Decimal(2.49), "1 lbs"),
		("Avocado", Decimal(1.25), "1 Avocado"),
		("Artichoke hearts", Decimal(3.99), "1 Artichoke"),
		("Brussels sprouts", Decimal(2.99), "1 lbs"),
		("Carrots", Decimal(1.79), "2 lbs"),
		("Spinach", Decimal(2.50), "376 grams"),
		("Celery", Decimal(1.89), "1 stalk"),
		("Broccoli", Decimal(3.99), "1 lbs"),
		("Zucchini", Decimal(1.69), "1 lbs"),
		("Cabbage", Decimal(2.55), "1 Cabbage"),
		("Peppers", Decimal(3.00), "2 Peppers"),
		("Cauliflower", Decimal(4.99), "1 Cauliflower"),
		("Eggplant", Decimal(1.99), "1 lbs"),
		("Sweet Potatoes", Decimal(5.00), "10 lbs"),
		("Coconut oil", Decimal(25.00), "750 mls Coconut Oil"),
		("Olive oil", Decimal(12.99), "750 mls Olive Oil"),
		("Grass-fed butter", Decimal(3.49), "1 lbs"),
		("Almonds", Decimal(5.99), "198 grams"),
		("Cashews", Decimal(4.99), "212 grams"),
		("Hazelnuts", Decimal(5.99), "226 grams"),
		("Pecans", Decimal(5.99), "226 grams"),
		("Pine nuts", Decimal(5.99), "113 grams"),
		("Pumpkin seeds", Decimal(2.99), "226 grams"),
		("Macadamia nuts", Decimal(100.00), "226 grams"),
		("Walnuts", Decimal(3.99), "212 grams"),
		("Apple", Decimal(1.99), "1 lbs"),
		("Blackberries", Decimal(4.99), "6 ounces"),
		("Papaya", Decimal(1.29), "1 lbs"),
		("Peaches", Decimal(100.00), "6 ounces"),
		("Plums", Decimal(100.00), "6 ounces"),
		("Mango", Decimal(1.25), "1 Mango"),
		("Blueberries", Decimal(3.50), "6 ounces"),
		("Grapes", Decimal(3.49), "1 lbs"),
		("Lemon", Decimal(1.50), "2 lemons"),
		("Strawberries", Decimal(100.00), "6 ounces"),
		("Watermelon", Decimal(100.00), "6 ounces"),
		("Lime", Decimal(1.00), "4 Limes"),
		("Raspberries", Decimal(3.99), "6 ounces"),
		("Cantaloupe", Decimal(3.99), "1 Cantaloupe"),
		("Tangerine", Decimal(3.99), "5 lbs"),
		("Figs", Decimal(100.00), "6 ounces"),
		("Oranges", Decimal(1.0), "1 Orange"),
		("Canned Sockeye Salmon", Decimal(4.51), "1 Package of Salmon")
	]

	conversion_factor_db = {
		"1 lbs": 4.5359237,
		'6 ounces': 1.70097139,
		'1 Mango': 2.07,
		'2 lemons': 2.16,
		'750 mls Olive Oil': 7.5,
		'1 Avocado': 2.01,
		'212 grams': 2.12,
		'1 stalk': 0.4,
		'1 Cauliflower': 5.75,
		'113 grams': 1.13,
		'1 Cantaloupe': 8.14,
		'2 Peppers': 1.19,
		'1 Cabbage': 9.08,
		'5 lbs': 4.5359237*5,
		'750 mls Coconut Oil': 7.5,
		'1 Orange': 1.31,
		'10 lbs': 4.5359237*10,
		'376 grams': 3.76,
		'1 Artichoke': 1.28,
		'2 lbs': 4.5359237*2,
		'4 Limes': 0.67*4,
		'198 grams': 1.98,
		'18 Eggs': 0.5*18,
		'226 grams': 2.26,
		'1 Package of Salmon': 0.56
	}

	for product_name, price, package_size in product_info:
		cur_product = Product.objects.get(name=product_name)

		cur_product.price = price
		cur_product.quanity_needed = package_size
		cur_product.conversion_factor = conversion_factor_db[package_size]

		for nutrition_fact in cur_product.nutrition_facts.all():
			nutrition_fact.quantity = nutrition_fact.quantity * Decimal(cur_product.conversion_factor)
			nutrition_fact.save()

		cur_product.has_been_converted = True
		cur_product.save()

	# print(1/0)

class Migration(migrations.Migration):

    dependencies = [
        ('nutrient', '0024_auto_20151219_0528'),
    ]

    operations = [
    	migrations.RunPython(add_conversion_factors),
    ]


import os
from unittest import mock

import pytest

from src.main.lambdas.iot_atlas_misc import app

@pytest.fixture()
def motor_driver_event():
    return {
        "address": "N/A",
        "addressType": "N/A",
        "name": "",
        "module": "Motor Driver",
        "version": "0.1",
        "reading": {
            "value": 20,
            "timestamp": 1631054894.9632235
        }
    }

@pytest.fixture()
def etape_event():
    return {
        "name": "rpi-ads1115-etape",
        "module": "eTape",
        "version": "0.2",
        "host": "25ee3924b3fd1ae1280c4442862eb844",
        "addressType": "I2C",
        "address": 72,
        "reading": {
            "type": "level",
            "value": 11483,
            "timestamp": 1633232725.3501136
        }
    }

@mock.patch('botocore.client.BaseClient._make_api_call')
@mock.patch.dict(os.environ, {"MQTT_TOPIC": "my-test-topic", "MQTT_ENDPOINT": "localhost"}, clear=True)
def test_lambda_handler(motor_driver_event):
    response = app.lambda_handler(motor_driver_event, "")
    assert "statusCode" in response
    assert "body" in response
    assert response['statusCode'] == 200
    assert response['body']['topic'] == 'my-test-topic'

@mock.patch('botocore.client.BaseClient._make_api_call')
@mock.patch.dict(os.environ, {"MQTT_TOPIC": "my-test-topic", "MQTT_ENDPOINT": "localhost"}, clear=True)
def test_lambda_handler2(etape_event):
    response = app.lambda_handler(etape_event, "")
    assert "statusCode" in response
    assert "body" in response
    assert response['statusCode'] == 200
    assert response['body']['topic'] == 'my-test-topic'


import sys
from HuffmanTree import HuffmanTreeNode
from bitstring import BitArray

def bitArrayToFile(string, fileName):
	"""Write the given bitstring into the file with the specified filename"""
	with open(fileName, 'wb') as file:
		string.tofile(file)

def stringToFile(string, fileName):
	"""Write the given string into the file with the specified filename"""
	with open(fileName, 'w') as file:
		file.write(string)

def getCharFrequencies(string):
	"""
	Produce a map of characters to the number of times they occur given
	a specified string of character
	"""
	freqs = {}
	for char in string:
		if char in freqs:
			# If the character is in the dictionary, add one to the count
			freqs[char] += 1
		else:
			# Otherwise, add it to the dictionary with a count of 1
			freqs[char] = 1
	return freqs

def encode(filename):
	"""Encode a given .txt file and return the encoded bit array"""
	# Read the file
	fileContent = ""
	with open(filename, 'r') as file:
		fileContent = file.read()

	# Get the frequences of each character
	frequencies = getCharFrequencies(fileContent)

	# Generate the Huffman Tree and the Code map
	Tree = HuffmanTreeNode.createFromFrequencies(frequencies)
	encodemap = Tree.getEncodeMap()

	# Encode the tree to a string, and then every character in the file
	# based on the code map
	encoding = Tree.toBitArray()
	for char in fileContent:
		encoding += encodemap[char]
	return encoding

def decode(filename):
	"""Decode a given .huff file and return the decoded string"""
	# Read the file
	fileContent = ""
	with open(filename, 'rb') as file:
		fileContent = BitArray(file.read())

	# Obtain the Huffman tree from the file
	Tree = HuffmanTreeNode().fromBitArray(fileContent)

	# Use the tree to decode the rest of the bytes
	text = ""
	while True:
		decodedChar = Tree.decodeChar(fileContent)
		if decodedChar is None:
			break
		text += decodedChar

	# Return the decoded text
	return text

def main(argv):
	# Check input arguments
	if (len(argv) < 3 or argv[1] == "-h"):
		print("Usage: python HuffmanCodec.py [--encode file.txt] [-decode file.huff]")
		return
	elif (not argv[2].endswith(".txt") and not argv[2].endswith(".huff")):
		print("File must either be .txt to encode or .huff to decode")
		return

	# Further check input arguments
	if (argv[1] == "--encode" and argv[2].endswith(".txt")):
		# Encode the text file, then write it to a huff file
		encoding = encode(argv[2])
		newFilename = argv[2][:-4] + ".huff"
		bitArrayToFile(encoding, newFilename)
	elif (argv[1] == "--decode" and argv[2].endswith(".huff")):
		# Decode the huff file, then write it to a text file
		decoding = decode(argv[2])
		newFilename = argv[2][:-5] + "-decoded.txt"
		stringToFile(decoding, newFilename)
	else:
		print("Usage: python HuffmanCodec.py [--encode file.txt] [-decode file.huff]")

if __name__ == "__main__":
	main(sys.argv)


import os.path as path
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.sql.expression import null

from secuml.core.data.predictions import Predictions
from secuml.core.classif.conf.classifiers import SemiSupervisedClassifierConf
from secuml.core.classif.conf.test.validation_datasets \
        import InvalidValidationDatasets
from secuml.exp import experiment
from secuml.exp.conf.annotations import AnnotationsConf
from secuml.exp.conf.dataset import DatasetConf
from secuml.exp.conf.features import FeaturesConf
from secuml.exp.tools.db_tables import DiademExpAlchemy
from secuml.exp.tools.db_tables import ExpAlchemy
from secuml.exp.tools.db_tables import ExpRelationshipsAlchemy
from secuml.exp.experiment import Experiment
from secuml.exp.tools.exp_exceptions import SecuMLexpException

from .conf.diadem import DiademConf
from .conf.detection import DetectionConf
from .conf.train import TrainConf
from .detection import DetectionExp
from .monitoring import CvMonitoring
from .train import TrainExp

class ExperimentNotFound(SecuMLexpException):

    def __init__(self, exp_id):
        self.exp_id = exp_id

    def __str__(self):
        return('The experiment %d cannot be found.' % (self.exp_id))

class InvalidModelExperimentKind(SecuMLexpException):

    def __init__(self, exp_kind):
        self.exp_kind = exp_kind

    def __str__(self):
        return('model-exp-id is a %s experiment '
               'while it must be a DIADEM or an ActiveLearning experiment.'
               % (self.exp_kind))

class InvalidInitClassifier(SecuMLexpException):

    def __init__(self, message):
        self.message = message

    def __str__(self):
        return self.message

def add_diadem_exp_to_db(session, exp_id, dataset_id, fold_id, kind,
                         classifier_conf=None):
    if classifier_conf is not None:
        multiclass = classifier_conf.multiclass
        proba = classifier_conf.is_probabilist()
        with_scoring = classifier_conf.scoring_function() is not None
        if kind in ['train', 'cv']:
            perf_monitoring = True
        elif kind in ['test', 'validation', 'alerts']:
            perf_monitoring = False
        model_interp = classifier_conf.is_interpretable()
        if kind == 'cv':
            predictions_interp = False
        else:
            predictions_interp = classifier_conf.interpretable_predictions()
        exp = DiademExpAlchemy(exp_id=exp_id, fold_id=fold_id,
                               dataset_id=dataset_id, type=kind,
                               perf_monitoring=perf_monitoring,
                               model_interp=model_interp,
                               pred_interp=predictions_interp,
                               multiclass=multiclass, proba=proba,
                               with_scoring=with_scoring)
    else:
        exp = DiademExpAlchemy(exp_id=exp_id, fold_id=fold_id,
                               dataset_id=dataset_id, type=kind)
    session.add(exp)
    session.flush()

def _get_exp_row(session, exp_id):
    query = session.query(ExpAlchemy)
    query = query.filter(ExpAlchemy.id == exp_id)
    try:
        return query.one()
    except NoResultFound:
        return None

class DiademExp(Experiment):

    def __init__(self, exp_conf, create=True, session=None):
        Experiment.__init__(self, exp_conf, create, session)
        self.test_conf = self.exp_conf.core_conf.test_conf
        self.validation_conf = self.exp_conf.core_conf.validation_conf
        self._init_children_exps()

    def run(self, instances=None, cv_monitoring=False,
            init_classifier=None):
        Experiment.run(self)
        datasets = self._gen_datasets(instances)
        if self.test_conf.method in ['cv', 'temporal_cv', 'sliding_window']:
            if init_classifier is not None:
                raise InvalidInitClassifier(
                        'Init classifier cannot be set for CV modes.')
            self._run_cv(datasets, cv_monitoring)
        else:
            self._run_one_fold(datasets, cv_monitoring,
                               init_classifier=init_classifier)

    def web_template(self):
        return 'diadem/main.html'

    def get_train_exp(self):
        return self._train_exp

    def get_detection_exp(self, kind):
        return self._detection_exp[kind]

    def get_predictions(self, kind):
        return self.get_detection_exp(kind).predictions

    def _create_train_exp(self, fold_id=None):
        diadem_id = self.exp_conf.exp_id
        exp_name = 'DIADEM_%i_Train' % diadem_id
        if fold_id is not None:
            exp_name = '%s_fold_%i' % (exp_name, fold_id)
        main_features_conf = self.exp_conf.features_conf
        features_conf = FeaturesConf(
                main_features_conf.input_features,
                main_features_conf.sparse,
                main_features_conf.logger,
                filter_in_f=main_features_conf.filter_in_f,
                filter_out_f=main_features_conf.filter_out_f)
        train_exp_conf = TrainConf(self.exp_conf.secuml_conf,
                                   self.exp_conf.dataset_conf,
                                   features_conf,
                                   self.exp_conf.annotations_conf,
                                   self.exp_conf.core_conf.classifier_conf,
                                   name=exp_name, parent=diadem_id,
                                   fold_id=fold_id)
        return TrainExp(train_exp_conf, session=self.session)

    def _set_train_exp_id(self):
        train_exp_id = self._check_already_trained_conf()
        exp_relation = ExpRelationshipsAlchemy(child_id=train_exp_id,
                                               parent_id=self.exp_conf.exp_id)
        self.session.add(exp_relation)
        return train_exp_id

    def _get_trained_classifier(self, train_exp_id):
        trained_exp = experiment.get_factory().from_exp_id(
                                                     train_exp_id,
                                                     self.exp_conf.secuml_conf,
                                                     self.session)
        trained_conf = trained_exp.exp_conf.core_conf
        trained_classifier = trained_conf.model_class(trained_conf)
        trained_classifier.load_model(path.join(trained_exp.output_dir(),
                                                'model.out'))
        return trained_classifier

    def _check_already_trained_conf(self):
        already_trained_id = self.exp_conf.already_trained
        model_exp = _get_exp_row(self.session, already_trained_id)
        # Check whether the experiment exists
        if model_exp is None:
            raise ExperimentNotFound(already_trained_id)
        # Check the type of the experiment
        if model_exp.kind == 'Diadem':
            query = self.session.query(DiademExpAlchemy)
            query = query.join(DiademExpAlchemy.exp)
            query = query.join(ExpAlchemy.parents)
            query = query.filter(
                       ExpRelationshipsAlchemy.parent_id == already_trained_id)
            query = query.filter(DiademExpAlchemy.type == 'train')
            query = query.filter(DiademExpAlchemy.fold_id == null())
            query = query.join(DiademExpAlchemy.exp)
            query = query.filter(ExpAlchemy.kind == 'Train')
            res = query.one()
            return res.exp_id
        elif model_exp.kind == 'ActiveLearning':
            return None
        else:
            raise InvalidModelExperimentKind(model_exp.kind)

    # kind in ['train', 'test', 'validation']
    def _create_detection_exp(self, kind, classifier_conf, fold_id=None):
        detection_confs = self._create_detection_conf(kind, classifier_conf,
                                                      fold_id=fold_id)
        global_exp = None
        if len(detection_confs) > 1:
            global_exp = self._create_global_detection_exp(
                                               kind,
                                               classifier_conf,
                                               detection_confs[0].dataset_conf)
            for detection_conf in detection_confs:
                detection_conf.parent = global_exp.exp_id
        return global_exp, [DetectionExp(detection_conf, session=self.session)
                            for detection_conf in detection_confs]

    def _create_detection_conf(self, kind, classifier_conf, fold_id=None):
        diadem_id = self.exp_conf.exp_id
        exp_name = 'DIADEM_%i_Detection_%s' % (diadem_id, kind)
        if fold_id is not None:
            exp_name = '%s_fold_%i' % (exp_name, fold_id)
        secuml_conf = self.exp_conf.secuml_conf
        logger = secuml_conf.logger
        main_features_conf = self.exp_conf.features_conf
        features_conf = FeaturesConf(
                main_features_conf.input_features,
                main_features_conf.sparse,
                main_features_conf.logger,
                filter_in_f=main_features_conf.filter_in_f,
                filter_out_f=main_features_conf.filter_out_f)
        if (kind == 'validation' or
                (kind == 'test' and self.test_conf.method == 'datasets')):
            validation_conf = getattr(self, '%s_conf' % kind)
            annotations_conf = AnnotationsConf('GROUND_TRUTH_IF_EXISTS', None,
                                               logger)
            if validation_conf.streaming:
                features_conf.streaming = True
                features_conf.stream_batch = validation_conf.stream_batch
            dataset_confs = [DatasetConf(self.exp_conf.dataset_conf.project,
                                         test_dataset,
                                         self.exp_conf.secuml_conf.logger)
                             for test_dataset in
                             validation_conf.validation_datasets]
        else:
            dataset_confs = [self.exp_conf.dataset_conf]
            annotations_conf = self.exp_conf.annotations_conf
        alerts_conf = None
        if fold_id is None and kind != 'train':
            alerts_conf = self.exp_conf.alerts_conf
        return [DetectionConf(secuml_conf, dataset_conf,
                              features_conf.deepcopy(), annotations_conf,
                              alerts_conf, name=exp_name, parent=diadem_id,
                              fold_id=fold_id, kind=kind)
                for dataset_conf in dataset_confs]

    # The dataset_conf is the conf of the first test dataset.
    # This way, the parameter 'has_ground_truth' has the right value.
    def _create_global_detection_exp(self, kind, classifier_conf,
                                     dataset_conf):
        diadem_id = self.exp_conf.exp_id
        exp_name = 'DIADEM_%i_GlobalDetection_%s' % (diadem_id, kind)
        secuml_conf = self.exp_conf.secuml_conf
        annotations_conf = self.exp_conf.annotations_conf
        main_features_conf = self.exp_conf.features_conf
        features_conf = FeaturesConf(
                main_features_conf.input_features,
                main_features_conf.sparse,
                main_features_conf.logger,
                filter_in_f=main_features_conf.filter_in_f,
                filter_out_f=main_features_conf.filter_out_f)
        alerts_conf = None
        return DetectionExp(DetectionConf(secuml_conf, dataset_conf,
                                          features_conf, annotations_conf,
                                          alerts_conf, name=exp_name,
                                          parent=diadem_id, kind=kind),
                            session=self.session)

    def _run_one_fold(self, datasets, cv_monitoring, fold_id=None,
                      init_classifier=None):
        classifier, train_time = self._train(datasets, cv_monitoring, fold_id,
                                             init_classifier)
        if not self.exp_conf.no_training_detection:
            train_data = datasets.train_instances
            if (isinstance(classifier.conf, SemiSupervisedClassifierConf) and
                    self.test_conf.method == 'unlabeled'):
                train_data = train_data.get_annotated_instances()
            self._detection('train', classifier, train_data, fold_id)
        test_predictions, test_time = self._detection('test', classifier,
                                                      datasets.test_instances,
                                                      fold_id)
        if self.validation_conf:
            self._detection('validation', classifier, None, fold_id)
        return classifier, train_time, test_predictions, test_time

    def _train(self, datasets, cv_monitoring, fold_id, init_classifier):
        if self.exp_conf.already_trained is not None:
            if init_classifier is not None:
                raise InvalidInitClassifier('Init classifier cannot be set in '
                                            'AlreadyTrained mode.')
            train_exp_id = self._set_train_exp_id()
            return self._get_trained_classifier(train_exp_id), 0
        else:
            train_exp = self._create_train_exp(fold_id=fold_id)
            train_exp.run(datasets.train_instances,
                          cv_monitoring=cv_monitoring,
                          init_classifier=init_classifier)
            if fold_id is None:
                self._set_train_exp(train_exp)
            return train_exp.classifier, train_exp.train_time

    # kind: train, test, validation
    def _detection(self, kind, classifier, instances, fold_id):
        global_exp, detection_exps = self._create_detection_exp(
                                                            kind,
                                                            classifier.conf,
                                                            fold_id=fold_id)
        if not all(detection_exp.exp_conf.dataset_conf.has_ground_truth ==
                   detection_exps[0].exp_conf.dataset_conf.has_ground_truth
                   for detection_exp in detection_exps):
            raise InvalidValidationDatasets(
                    'All the validation datasets must contain ground truth '
                    'annotations, or none of them.')
        if fold_id is None:
            exp = global_exp if global_exp is not None else detection_exps[0]
            self._set_detection_exp(kind, exp)
        global_predictions = None
        global_prediction_time = None
        for detection_exp in detection_exps:
            detection_exp.run(instances, classifier)
            predictions = detection_exp.predictions
            prediction_time = detection_exp.prediction_time
            if global_exp is not None:
                if global_predictions is None:
                    global_predictions = Predictions.deepcopy(predictions)
                    global_prediction_time = prediction_time
                else:
                    global_predictions.union(predictions)
                    global_prediction_time.add(prediction_time)
        if global_exp is not None:
            global_exp.set_predictions(global_predictions,
                                       global_prediction_time)
        return predictions, prediction_time

    def _run_cv(self, cv_datasets, cv_monitoring):
        classifiers = [None for _ in range(self.test_conf.num_folds)]
        classifier_conf = self.exp_conf.core_conf.classifier_conf
        dataset_id = self.exp_conf.dataset_conf.dataset_id
        add_diadem_exp_to_db(self.session, self.exp_conf.exp_id, dataset_id,
                             None, 'cv', classifier_conf=classifier_conf)
        global_cv_monitoring = CvMonitoring(self, self.test_conf.num_folds)
        for fold_id, datasets in enumerate(cv_datasets._datasets):
            classifier, train_t, predictions, test_t = self._run_one_fold(
                                                                 datasets,
                                                                 cv_monitoring,
                                                                 fold_id)
            global_cv_monitoring.add_fold(classifier, train_t, predictions,
                                          test_t, fold_id)
            classifiers[fold_id] = classifier
        global_cv_monitoring.display(self.output_dir())
        return classifiers

    def _gen_datasets(self, instances):
        if instances is None:
            instances = self.get_instances()
        classifier_conf = self.exp_conf.core_conf.classifier_conf
        return self.test_conf.gen_datasets(classifier_conf, instances)

    # kind in ['train', 'test', 'validation']
    def _set_detection_exp(self, kind, exp):
        self._detection_exp[kind] = exp

    def _set_train_exp(self, exp):
        self._train_exp = exp

    def _init_children_exps(self):
        self._train_exp = None
        if self.test_conf.method in ['cv', 'temporal_cv', 'sliding_window']:
            self._detection_exp = None
        else:
            self._detection_exp = {}
            for kind in ['train', 'test', 'validation']:
                self._detection_exp[kind] = None

experiment.get_factory().register('Diadem', DiademExp, DiademConf)


from numpy import random
import warnings
warnings.filterwarnings("ignore") #suppress warnings
from task0 import *
from task1 import *

class Loss_MSE:

    # Forward pass of MSE
    def forward(self, y_pred, y_true):
        MSE = ((y_pred - y_true) ** 2).mean(axis=None)
        return MSE

    # Backward pass
    def backward(self, dvalues, labels):
        self.dvalues = dvalues
        self.dvalues = 0.5 * (labels-dvalues)

class Optimizer_SGD:

    # Initialize optimizer - set settings,
    # learning rate of 1. is default for this optimizer
    def __init__(self, learning_rate=0.003):
        self.learningRate = learning_rate

        self.lowest_loss = 9999999  # some initial value
        self.best_inputLayer_weights = inputLayer.weights
        self.best_inputLayer_biases = inputLayer.biases
        self.best_layer1_weights = layer1.weights
        self.best_layer1_biases = layer1.biases
        self.best_layer2_weights = layer2.weights
        self.best_layer2_biases = layer2.biases

     # Update parameters
    def update_params(self, inputLayer, layer1, layer2, loss):

        # Update weights with some small random values SGD way
        #inputLayer.weights -= self.learningRate * inputLayer.dweights
        #inputLayer.biases -= self.learningRate * inputLayer.dbiases
        #layer1.weights -= self.learningRate * layer1.dweights
        #layer1.biases -= self.learningRate * layer1.dbiases
        #layer2.weights -= self.learningRate * layer2.dweights
        #layer2.biases -= self.learningRate * layer2.dbiases

        # Updating them in a random way, which yielded results
        inputLayer.weights += self.learningRate * np.random.randn(2, 10)
        inputLayer.biases += self.learningRate * np.random.randn(1, 10)
        layer1.weights += self.learningRate * np.random.randn(10, 10)
        layer1.biases += self.learningRate * np.random.randn(1, 10)
        layer2.weights += self.learningRate * np.random.randn(10, 2)
        layer2.biases += self.learningRate * np.random.randn(1, 2)

        if loss < self.lowest_loss:
            #print('New set of weights found, iteration:', epoch, 'loss:', loss, 'acc:', accuracy)
            self.best_inputLayer_weights = inputLayer.weights
            self.best_inputLayer_biases = inputLayer.biases
            self.best_layer1_weights = layer1.weights
            self.best_layer1_biases = layer1.biases
            self.best_layer2_weights = layer2.weights
            self.best_layer2_biases = layer2.biases
            self.lowest_loss = loss
            # revert weights and biases
        else:
            inputLayer.weights = self.best_inputLayer_weights
            inputLayer.biases = self.best_inputLayer_biases
            layer1.weights = self.best_layer1_weights
            layer1.biases = self.best_layer1_biases
            layer2.weights = self.best_layer2_weights
            layer2.biases = self.best_layer2_biases

# Setting loss function
loss_function = Loss_MSE()

# Setting optimizer
optimizer = Optimizer_SGD()

# Task 3: Backward pass of the Network

for epoch in range(10000):

    # Input layer (2) -> Fully connected layer (10) -> ReLU -> Fully connected layer (10) -> ReLU ->
    # Fullyconnected(output)layer(2)
    inputLayer.forward(training_dataset)
    layer1.forward(inputLayer.output)
    activation1.forward(layer1.output)
    layer2.forward(activation1.output)
    activation2.forward(layer2.output)

    # Calculate loss (from activation output, MSE activation here)
    loss = loss_function.forward(activation2.output, training_label)

    # Checking accuracy for the output compared to the one hot encoded labels
    # Are they predicting the same, then 1 is added to correct, lastly divided by total rows in the dataset.
    correct = 0
    total = 0
    for i in range(len(training_dataset)):
        act_label = np.argmax(training_label[i])  # act_label = 1 (index)
        pred_label = np.argmax(activation2.output[i])  # pred_label = 1 (index)
        if act_label == pred_label:
            correct += 1
        total += 1
    accuracy = (correct / total) * 100

    if not epoch % 1000:
      print('epoch:', epoch, 'loss:', loss, 'acc:', accuracy)

    # Backward pass
    loss_function.backward(activation2.output, training_label)
    activation2.backward(loss_function.dvalues)
    layer2.backward(activation2.dvalues)
    activation1.backward(layer2.dvalues)
    layer1.backward(activation1.dvalues)
    inputLayer.backward(layer1.dvalues)

    # Update weight and biases with SGD, sending in loss to track it.
    optimizer.update_params(inputLayer, layer1, layer2, loss)


# Программа "Автодиллер"
# Глава 2 Задание 4
# Вычисляет конечную стоимоть автомобиля

stoimst = (int(input('\nВведите стоимость автомобиля без учета наценок ')))
nalg = int(stoimst * 0.2)
reg_sbor = int(stoimst * 0.15)
agent_sbor = int(60000)
tsena_dstavki = int(5000)
summ = stoimst + nalg + reg_sbor + agent_sbor + tsena_dstavki
print('\nИтоговая сумма покупки ', summ,)
input()


from torch import nn

from yolov3_modules import Darknet53, YOLOv3_FPN, YOLOv3_head

class YOLOv3_Model(nn.Module):
    """_summary_

    Args:
        nn (_type_): _description_
    """
    def __init__(self, input_size, num_classes, anchors):
        super().__init__()
        self.backbone = Darknet53()
        self.fpn = YOLOv3_FPN()
        self.head = YOLOv3_head(input_size=input_size, num_classes=num_classes, anchors=anchors)

    def forward(self, x):
        x1, x2, x3 = self.backbone(x)
        out_l, out_m, out_s = self.fpn(x1, x2, x3)
        predictions = self.head(out_l, out_m, out_s)
        return predictions


from collections import deque

n = int(input())
m = int(input())
q = deque()
a = [[] for _ in range(n+1)]
c = [0 for _ in range(n+1)]

for i in range(m):
    row = list(map(int, input().split()))
    a[row[0]].append(row[1])
    a[row[1]].append(row[0])

q.append(1)
c[1] = 1
while q:
    x = q.popleft()
    c[x] = 1
    for nx in a[x]:
        if not c[nx]:
            c[nx] = 1
            q.append(nx)
print(sum(c)-1)

# a를 미로찾기 bfs처럼 방문하는게 특이함.
# : 초기화 때 무식하게 0으로 해 주는게 아니라 정점 1에 해당하는 정점을 나열되는 리스트 방식으로 구현
# 사실상 진정한 그래프는 직관적으로 이게 더 들어맞는 방식, 탐색 속도를 더 줄일 수 있는 방식.


from odoo.tests import HttpCase, tagged

@tagged('-at_install', 'post_install')
class TestUi(HttpCase):
    def setUp(self):
        super(TestUi, self).setUp()
        # create a Chair floor protection product
        self.env['product.product'].create({
            'name': 'Chair floor protection',
            'type': 'consu',
            'website_published': True,
            'list_price': 1000,
        })
        # create a Customizable Desk product
        self.env['product.product'].create({
            'name': 'Customizable Desk',
            'type': 'consu',
            'website_published': True,
            'list_price': 1000,
        })
        # create a Warranty product
        self.env['product.product'].create({
            'name': 'Warranty',
            'type': 'service',
            'website_published': True,
            'list_price': 20,
        })

    def test_onsite_payment_tour(self):
        # Make sure at least one onsite payment option exists.
        self.env['delivery.carrier'].create({
            'delivery_type': 'onsite',
            'is_published': True,
            'website_published': True,
            'name': 'Example shipping On Site',
            'product_id': self.env.ref('website_sale_picking.onsite_delivery_product').id,
        })
        self.env.ref("website_sale_picking.payment_provider_onsite").state = 'enabled'
        self.env.ref("website_sale_picking.payment_provider_onsite").is_published = True

        self.start_tour('/shop', 'onsite_payment_tour')