// (C) 2002 Jasper Bedaux, ITFA, University of Amsterdam
// http://www.bedaux.net/jasper/
// C++ header for input-output relations for neural network

#ifndef IO_PATTERNS_H
#define IO_PATTERNS_H

#include <vector>
#include <string>

class Pattern { // one pattern
public:
  int size() const { return p.size(); } // size
  int na() const { return nactive; } // number of elements that are 1
  bool operator[](int i) const { return p[i]; } // return i-th element
  const std::vector<bool>& operator()() const { return p; } // return as vector

  Pattern() : nactive(0) {} // default constructor
  Pattern(int n, int a) throw (std::string); // construct random pattern
  Pattern(const std::string&) throw (std::string); // construct from string
  Pattern(const Pattern& pat) : p(pat.p), nactive(pat.nactive) {} // copy constructor
  Pattern& operator=(const Pattern& pat) { // assignment operator
    if (&pat != this) { p = pat.p; nactive = pat.nactive; }
    return *this;
  }
  ~Pattern() {}
private:
  std::vector<bool> p; // the pattern
  int nactive; // number of elements that are 1
};

class Relation { // one relation consisting of input and output pattern
public:
  Pattern input;
  Pattern output;
  int id() const { return number; }

  Relation(int index = 0) : number(index) {} // default constructor
// construct with input pattern and output pattern
  Relation(int index, const Pattern& in, const Pattern& out) :
    input(in), output(out), number(index) {}
// construct random input output pattern with specified sizes and activities
  Relation(int index, int ni, int no, int nai, int nao) :
    input(ni, nai), output(no, nao), number(index) {}
// construct from two strings with '0' and '1'
  Relation(int index, const std::string& in, const std::string& out) :
    input(in), output(out), number(index) {}
  Relation(const Relation& r) : // copy constructor
    input(r.input), output(r.output), number(r.number) {}
  Relation& operator=(const Relation& r) { // assignment operator
    if (&r != this) { input = r.input; output = r.output; number = r.number; }
    return *this;
  }
  ~Relation() {}
private:
  int number; // identification number
};

class RelationSet { // collection of input-output relations
public:
  int size() const { return p.size(); } // returns number of relations
  double ai() const { return ainput; } // average input activity
  double ao() const { return aoutput; } // average output activity
  void shuffle(); // shuffle order of input-output relations
  const Relation& operator[](int i) const { return p[i]; }

  RelationSet() : ainput(0.), aoutput(0.) {} // default constructor
// constructor for random input-output relations
  RelationSet(int nio, int ni, int no, int nai, int nao) throw (std::string);
// constructor for reading relations from file
  RelationSet(const std::string& patternfile) throw (std::string);
  RelationSet(const RelationSet& r) : // copy constructor
    p(r.p), ainput(r.ainput), aoutput(r.aoutput) {}
  RelationSet& operator=(const RelationSet& r) { // assignment operator
    if (&r != this) { p = r.p; ainput = r.ainput; aoutput = r.aoutput; }
    return *this;
  }
  ~RelationSet() {}
private:
  std::vector<Relation> p;
  double ainput; // average input activity
  double aoutput; // average output activity
};

#endif // IO_PATTERNS_H