/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   Layer.hpp
 * Author: jens
 *
 * Created on 25. Oktober 2019, 08:13
 */

#ifndef RBMLAYER_HPP
#define RBMLAYER_HPP

#include <string>

#include <armadillo>
#include <jsoncpp/json/json.h>
#include "Rbm.hpp"

class Layer : public Rbm
{
public:
	Layer *next;
	Layer *prev;

	Layer(const std::string &name, size_t id, size_t numVisibleX, size_t numVisibleY, size_t numHidden);
	Layer(const Layer& orig);
	virtual ~Layer();

	Json::Value toJson() const;
	bool loadWeights(const std::string &prjname="");
	bool saveWeights(const std::string &prjname="");

	void train(arma::mat const &batch, IListener *pListener=nullptr)
	{
		Rbm::train(trainingData(batch), pListener);
	}
	
	std::string& name()
	{
		return m_name;
	}
	
	size_t id()
	{
		return m_id;
	}
	
	int numVisibleX()
	{
		return m_numVisibleX;
	}

	int numVisibleY()
	{
		return m_numVisibleY;
	}
	
	int numHidden()
	{
		return m_bh.n_elem;
	}

	arma::mat trainingData(arma::mat const &batch)
	{
		arma::mat thisBatch = batch;
		Layer *pLayer = root();
		while (pLayer)
		{
			if (pLayer == this)
			{
				break;
			}
			thisBatch = pLayer->toHiddenProbs(thisBatch);
			pLayer = pLayer->next;
		}
		return thisBatch;
	}
		
	Layer *root()
	{
		Layer *pLayer = this;
		while(pLayer->prev)
		{
			pLayer = pLayer->prev;
		}
		return pLayer;
	}

private:
	
	std::string m_name;
	std::string m_weightsFile;
	size_t m_id;
	size_t m_numVisibleX;
	size_t m_numVisibleY;

};

#endif /* RBMLAYER_HPP */

