# Path: amdtk/io/persistent_model.py
# class PersistentModel(metaclass=abc.ABCMeta):
#     """Base class for classes that can be serialized."""
# 
#     @abc.abstractmethod
#     def to_dict(self):
#         """Get the data of the model into a dictionary.
# 
#         Returns
#         -------
#         dict : dictionary
#             Dictionary containing the model's data.
# 
#         """
#         pass
# 
#     @abc.abstractclassmethod
#     def load_from_dict(cls, model_data):
#         """Create and initialize the model from a dictionary.
# 
#         Parameters
#         ----------
#         model_data : dictionary
#             Dictionary containing the model's data.
# 
#         Returns
#         -------
#         model : :class:`PersistentModel`
#             Model initialized from the data.
# 
#         """
#         pass
# 
#     def save(self, fname):
#         """Store the model.
# 
#         Parameters
#         ----------
#         fname : string
#             String where to store the model.
# 
#         """
#         retval = self.to_dict()
#         retval['class'] = self.__class__
#         with open(fname, 'wb') as fid:
#             pickle.dump(retval, fid)
# 
#     @staticmethod
#     def load(file_obj):
#         """Load a model.
# 
#         Parameters
#         ----------
#         file_obj : file object
#             File-like object  where to store the model.
# 
#         Returns
#         -------
#         model : :class:`PersistentModel`
#             Model initialized from the stored data.
# 
#         """
#         model_data = pickle.load(file_obj)
#         cls = model_data['class']
#         return cls.load_from_dict(model_data)
# 
# Path: amdtk/models/mlp_utils.py
# class GaussianNeuralNetwork(NeuralNetwork):
# 
#     def __init__(self, structure, inputs=None, n_samples=10):
#         NeuralNetwork.__init__(self, structure, inputs)
#         self.mean = self.layers[-1].outputs
#         self.var = self.layers[-1].var
#         self.n_samples = n_samples
# 
#         # Noise variable for the reparameterization trick.
#         if "gpu" in theano.config.device:
#             srng = theano.sandbox.cuda.rng_curand.CURAND_RandomStreams(123)
#         else:
#             srng = T.shared_randomstreams.RandomStreams()
#             self.eps = srng.normal((n_samples, self.mean.shape[0],
#                                     self.mean.shape[1]))
# 
#         # Latent variable.
#         self.sample = self.mean + T.sqrt(self.var) * self.eps
# 
#         self.sample = T.reshape(self.sample,
#             (n_samples * self.mean.shape[0], -1))
# 
#         # Build the functions.
#         self.forward = theano.function(
#             inputs=[self.inputs],
#             outputs=[self.mean, self.var]
#         )
# 
# Path: amdtk/models/mlp_utils.py
# class NeuralNetwork(object):
# 
#     def __init__(self, structure, inputs=None):
#         # Build the neural network.
#         self.layers = []
#         self.params = []
#         current_inputs = inputs
#         for layer_struct in structure:
#             layer_type = layer_struct[0]
#             layer_params = layer_struct[1:]
# 
#             logger.debug('create nnet layer type={layer_type} '
#                 'params={params}'.format(layer_type=layer_type,
#                                          params=layer_params))
# 
#             self.layers.append(
#                 LAYER_TYPES[layer_type](
#                     current_inputs,
#                     *layer_params
#                 )
#             )
#             self.params += self.layers[-1].params
#             current_inputs = self.layers[-1].outputs
# 
#         self.inputs = self.layers[0].inputs
#         self.outputs = self.layers[-1].outputs


import abc
import pickle
import numpy as np
import theano
import theano.tensor as T
from ..io import PersistentModel
from .mlp_utils import GaussianNeuralNetwork
from .mlp_utils import NeuralNetwork

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

"""



class SVAE(PersistentModel):

    def __init__(self, encoder_struct, decoder_struct, prior_latent,
                n_samples=10):

        self.n_samples = n_samples
        self.encoder_struct = encoder_struct
        self.decoder_struct = decoder_struct
        self.prior_latent = prior_latent

        self._build()

    def _build(self):

# Path: amdtk/io/persistent_model.py
# class PersistentModel(metaclass=abc.ABCMeta):
#     """Base class for classes that can be serialized."""
# 
#     @abc.abstractmethod
#     def to_dict(self):
#         """Get the data of the model into a dictionary.
# 
#         Returns
#         -------
#         dict : dictionary
#             Dictionary containing the model's data.
# 
#         """
#         pass
# 
#     @abc.abstractclassmethod
#     def load_from_dict(cls, model_data):
#         """Create and initialize the model from a dictionary.
# 
#         Parameters
#         ----------
#         model_data : dictionary
#             Dictionary containing the model's data.
# 
#         Returns
#         -------
#         model : :class:`PersistentModel`
#             Model initialized from the data.
# 
#         """
#         pass
# 
#     def save(self, fname):
#         """Store the model.
# 
#         Parameters
#         ----------
#         fname : string
#             String where to store the model.
# 
#         """
#         retval = self.to_dict()
#         retval['class'] = self.__class__
#         with open(fname, 'wb') as fid:
#             pickle.dump(retval, fid)
# 
#     @staticmethod
#     def load(file_obj):
#         """Load a model.
# 
#         Parameters
#         ----------
#         file_obj : file object
#             File-like object  where to store the model.
# 
#         Returns
#         -------
#         model : :class:`PersistentModel`
#             Model initialized from the stored data.
# 
#         """
#         model_data = pickle.load(file_obj)
#         cls = model_data['class']
#         return cls.load_from_dict(model_data)
# 
# Path: amdtk/models/mlp_utils.py
# class GaussianNeuralNetwork(NeuralNetwork):
# 
#     def __init__(self, structure, inputs=None, n_samples=10):
#         NeuralNetwork.__init__(self, structure, inputs)
#         self.mean = self.layers[-1].outputs
#         self.var = self.layers[-1].var
#         self.n_samples = n_samples
# 
#         # Noise variable for the reparameterization trick.
#         if "gpu" in theano.config.device:
#             srng = theano.sandbox.cuda.rng_curand.CURAND_RandomStreams(123)
#         else:
#             srng = T.shared_randomstreams.RandomStreams()
#             self.eps = srng.normal((n_samples, self.mean.shape[0],
#                                     self.mean.shape[1]))
# 
#         # Latent variable.
#         self.sample = self.mean + T.sqrt(self.var) * self.eps
# 
#         self.sample = T.reshape(self.sample,
#             (n_samples * self.mean.shape[0], -1))
# 
#         # Build the functions.
#         self.forward = theano.function(
#             inputs=[self.inputs],
#             outputs=[self.mean, self.var]
#         )
# 
# Path: amdtk/models/mlp_utils.py
# class NeuralNetwork(object):
# 
#     def __init__(self, structure, inputs=None):
#         # Build the neural network.
#         self.layers = []
#         self.params = []
#         current_inputs = inputs
#         for layer_struct in structure:
#             layer_type = layer_struct[0]
#             layer_params = layer_struct[1:]
# 
#             logger.debug('create nnet layer type={layer_type} '
#                 'params={params}'.format(layer_type=layer_type,
#                                          params=layer_params))
# 
#             self.layers.append(
#                 LAYER_TYPES[layer_type](
#                     current_inputs,
#                     *layer_params
#                 )
#             )
#             self.params += self.layers[-1].params
#             current_inputs = self.layers[-1].outputs
# 
#         self.inputs = self.layers[0].inputs
#         self.outputs = self.layers[-1].outputs


# Path: amdtk/models/vae.py
import abc
import pickle
import numpy as np
import theano
import theano.tensor as T
from ..io import PersistentModel
from .mlp_utils import GaussianNeuralNetwork
from .mlp_utils import NeuralNetwork


The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

"""



class SVAE(PersistentModel):

    def __init__(self, encoder_struct, decoder_struct, prior_latent,
                n_samples=10):

        self.n_samples = n_samples
        self.encoder_struct = encoder_struct
        self.decoder_struct = decoder_struct
        self.prior_latent = prior_latent

        self._build()

    def _build(self):

        self.encoder = GaussianNeuralNetwork(self.encoder_struct,