// Global marking (PlaceMarking for each place) -*- c++ -*-

#ifndef GLOBALMARKING_H_
# define GLOBALMARKING_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

# include "PlaceMarking.h"
# include "BitBuffer.h"

/** @file GlobalMarking.h
 * Assignment of markings for each place
 */

/* Copyright © 1999-2002 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

class Net;

/** Global marking (PlaceMarking for each place) */
class GlobalMarking
{
public:
  /** Constructor */
  explicit GlobalMarking (const class Net& net);
  /** Copy constructor */
  explicit GlobalMarking (const class GlobalMarking& old);
  /** Assignment operator */
  class GlobalMarking& operator= (const class GlobalMarking& old);
  /** Destructor */
  ~GlobalMarking ();

# ifndef NDEBUG
  /** Get the net associated with the marking */
  const class Net& getNet () const { return myNet; }
# endif // NDEBUG
  /** Get the number of place markings */
  unsigned getSize () const { return mySize; }

  /** Get a PlaceMarking by place number */
  class PlaceMarking& operator[] (unsigned i) {
    assert (i < mySize);
    return myPlaceMarkings[i];
  }
  /** Get a PlaceMarking by place number */
  const class PlaceMarking& operator[] (unsigned i) const {
    return (*const_cast<class GlobalMarking*>(this))[i];
  }

  /** Get a PlaceMarking by place */
  class PlaceMarking& operator[] (const class Place& place);
  /** Get a PlaceMarking by place */
  const class PlaceMarking& operator[] (const class Place& place) const {
    return (*const_cast<class GlobalMarking*>(this))[place];
  }

  /** Flag the state erroneous */
  void flagErroneous () { myErroneous = true; }
  /** Determine whether the state is erroneous */
  bool isErroneous () const { return myErroneous; }

#ifndef NDEBUG
  /** Equality comparison
   * @param other	object to be compared with
   * @return		true if the objects are equal
   */
  bool operator== (const class GlobalMarking& other) const {
    assert (&myNet == &other.myNet && mySize == other.mySize);
    for (unsigned i = 0; i < mySize; i++)
      if (!(myPlaceMarkings[i] == other.myPlaceMarkings[i]))
	return false;
    return true;
  }
#endif // NDEBUG

  /** Encode this marking
   * @param buf		buffer to receive the encoded marking
   * @param m0		initial marking of the system
   * @param errorplace	placeholder for the identity of an erroneous place
   * @return		false in case of an integrity violation
   */
  bool encode (class BitPacker& buf,
	       const class GlobalMarking& m0,
	       card_t* errorplace) const;

  /** Encode this marking to a subnet marking
   * @param buf		buffer to receive the encoded marking
   * @param net		the subnet
   */
  void encode (class BitPacker& buf,
	       const class Net& net) const;

  /** Decode a marking to this
   * @param m0		initial marking of the system
   * @param data	the word-aligned encoded representation
   * @param propBits	number of bits needed for presenting the property state
   * @return		the property state number, or 0 if propBits == 0
   */
  unsigned decode (const class GlobalMarking& m0,
		   const word_t* data,
		   unsigned propBits = 0);

  /** Decode a subnet marking to this, replacing the place markings
   * @param net		the subnet
   * @param data	the word-aligned encoded representation
   */
  void decode (const class Net& net,
	       const word_t* data);

  /** Compute the markings of implicit places
   * @param m0		initial marking of the system
   */
  void computeImplicit (const class GlobalMarking& m0);

  /** Evaluate a Boolean condition
   * @param cond	the condition expression (state proposition)
   * @return		true if the condition holds; false otherwise
   */
  bool eval (const class Expression& cond) const;

  /** Display this object
   * @param printer	The printer object
   */
  void display (const class Printer& printer) const;

private:
# ifndef NDEBUG
  /** The net this marking belongs to */
  const class Net& myNet;
# endif // NDEBUG
  /** Flag: is the marking erroneous (is an erroneous transition enabled?) */
  bool myErroneous;
  /** Number of place markings (or places in the net) */
  unsigned mySize;
  /** The place markings */
  class PlaceMarking* myPlaceMarkings;
};

#endif // GLOBALMARKING_H_
