Please review any and all PUBLIC repositories, groups and associate files. These allow anyone on the Internet to access without authentication. Repository and group owners are responsible for their content and permission settings. Go to your project(s), click on Settings > General and expand the "Visibility, project features, permissions" to change this setting.

...
 
Commits (3)
.DS_Store
\ No newline at end of file
.DS_Store
build/
output/
\ No newline at end of file
//
// Interval.h
// for interval attributes
// Created by Mikhail Auguston on 5/24/18.
//
// last modified 01/02/2019
//=========================================
#include <iostream>
using namespace std;
float max(float a, float b){
return (a>=b)?a:b;
}
class Interval {
public:
float smallest, largest;
// constructors
Interval(){
smallest= largest= 0.0;
}
Interval(float s){
smallest= largest= s;
}
Interval(float s, float g){
smallest= (s <= g)?s:g;
largest= (s >= g)?s:g;
}
//-------------
float len(){
return (largest - smallest);
}
bool operator==(Interval &a){
return smallest == a.smallest && largest == a.largest;
}
bool operator!=(Interval &a){
return smallest != a.smallest || largest != a.largest;
}
bool operator>(Interval &a){
return smallest > a.largest;
}
bool operator>=(Interval &a){
return smallest >= a.largest;
}
bool operator<(Interval &a){
return largest < a.smallest;
}
bool operator<=(Interval &a){
return largest <= a.smallest;
}
Interval operator+(Interval &a){
Interval t;
t.smallest = smallest + a.smallest;
t.largest = largest + a.largest;
return t;
}
Interval operator-(Interval &a){
Interval t;
t.smallest = smallest - a.largest;
t.largest = largest - a.smallest;
return t;
}
Interval operator*(Interval &a){
Interval t;
t.smallest = smallest * a.smallest;
t.largest = largest * a.largest;
return t;
}
Interval operator/(Interval &a){
Interval t;
t.smallest = smallest / a.largest;
t.largest = largest / a.smallest;
return t;
}
// compound assignment operations
//-------------------------------
Interval &operator+=(const Interval &a){
smallest += a.smallest;
largest += a.largest;
return *this;
}
Interval &operator-=(const Interval &a){
smallest -= a.smallest;
largest -= a.largest;
return *this;
}
Interval &operator*=(const Interval &a){
smallest *= a.smallest;
largest *= a.largest;
return *this;
}
Interval &operator/=(const Interval &a){
smallest /= a.smallest;
largest /= a.largest;
return *this;
}
// for Interval and number mix
// Interval op float
bool operator==(float a){
return smallest == a && largest == a;
}
bool operator!=(float a){
return smallest != a || largest != a;
}
bool operator>(float a){
return smallest > a;
}
bool operator>=(float a){
return smallest >= a;
}
bool operator<(float a){
return largest < a;
}
bool operator<=(float a){
return largest <= a;
}
Interval &operator=(const float a){
smallest = a;
largest = a;
return *this;
}
Interval operator+(float a){
Interval t;
t.smallest = smallest + a;
t.largest = largest + a;
return t;
}
Interval operator-(float a){
Interval t;
t.smallest = smallest - a;
t.largest = largest - a;
return t;
}
Interval operator*(float a){
Interval t;
t.smallest = smallest * a;
t.largest = largest * a;
return t;
}
Interval operator/(float a){
Interval t;
t.smallest = smallest / a;
t.largest = largest / a;
return t;
}
Interval &operator+=(const float a){
smallest += a;
largest += a;
return *this;
}
Interval &operator-=(const float a){
smallest -= a;
largest -= a;
return *this;
}
Interval &operator*=(const float a){
smallest *= a;
largest *= a;
return *this;
}
Interval &operator/=(const float a){
smallest /= a;
largest /= a;
return *this;
}
}; // end class Interval
// independent functions on intervals
//-----------------------------------
// float op Interval
inline Interval operator+(float x, Interval y){
Interval temp(x + y.smallest, x + y.largest);
return temp;
}
inline Interval operator-(float x, Interval y){
Interval temp( x - y.largest, x - y.smallest);
return temp;
}
inline Interval operator*(float x, Interval y){
Interval temp(x * y.smallest, x * y.largest);
return temp;
}
inline Interval operator/(float x, Interval y){
Interval temp(x / y.largest, x / y.smallest);
return temp;
}
inline bool operator==(float x, Interval y){
return ( x == y.smallest && x == y.largest);
}
inline bool operator!=(float x, Interval y){
return ( x != y.smallest || x != y.largest);
}
inline bool operator>(float x, Interval y){
return ( x > y.largest);
}
inline bool operator<(float x, Interval y){
return ( x < y.smallest);
}
inline bool operator>=(float x, Interval y){
return ( x >= y.largest);
}
inline bool operator<=(float x, Interval y){
return ( x <= y.smallest);
}
// overloaded << operator
std::ostream &operator<<(std::ostream &stream, Interval a){
stream<<'['<< a.smallest << ".." << a.largest<< ']';
return stream;
}
// global_objects.h
//
// Created by Mikhail Auguston on 2/8/19.
//
//***** VIEW object infrastructure for trace list ******
using namespace std;
//-------------------------------------------------
class report_object{
public:
string title;
vector<string> report_contents;
// constructor
report_object(){ title = " "; }
void clean(){
report_contents.clear();
}
//--- print json for Report objects
void print_report_json(){
JSON<< endl<< "{\"REPORT\":["<< "\""<< title<< "\"";
vector<string>::iterator p;
for(p = report_contents.begin(); p != report_contents.end(); p++){
JSON<<",\"" << *p<< "\"";
}
JSON<<"]}"<< endl;
}
};
//--------------------------------------------------
class graph_object{
public:
string title;
// unique_node_id -> node_label
vector<string> nodes;
// from_node_id -> <to_node_id, arrow_label>
// no repetitions of <to_node_id, arrow_label> for same from_node_id
multimap<int, pair<int, string> > arrows; // edges with arrowheads
multimap<int, pair<int, string> > lines; // edges without arrowheads
//=============================================
// constructor
graph_object(){ title = " "; }
void clean(){
nodes.clear();
arrows.clear();
lines.clear();
}
// NEW NODE()
int create_new_node(string label){
nodes.push_back(label);
return nodes.size() - 1;
}
// find the last appearance of a node with a given label
int find_node(string label){
int result = -1;
for(int i = 0; i < nodes.size(); i++){
if(nodes[i] == label) result = i;
}
return result;
}
// LAST NODE()
int find_or_create_new_node(string label){
int x = find_node(label);
if(x >= 0) return x;
else return create_new_node(label);
}
void add_arrow(int n1, int n2, string arrow_label){
// if n1 or n2 does not exist - do nothing
if(n1 < 0 || n2 < 0 || n1 >= nodes.size() || n2 >= nodes.size()) return;
multimap<int, pair<int, string> >:: iterator p;
pair<int, string> p3;
for(p = arrows.begin(); p != arrows.end(); p++){
p3 = p->second;
// if arrow with that label already exists - do nothing
if(p->first == n1 && p3.first == n2 && p3.second == arrow_label) return;
}
// arrow n1 -> n2, arrow_label has not been found
arrows.insert(pair<int, pair<int, string> >(n1, pair<int, string>(n2, arrow_label)));
}
void add_line(int n1, int n2, string arrow_label){
// if n1 or n2 does not exist - do nothing
if(n1 < 0 || n2 < 0 || n1 >= nodes.size() || n2 >= nodes.size()) return;
// ensure that n1 <= n2
int temp = n1;
if(n1 > n2) {
n1 = n2;
n2 = temp;
};
multimap<int, pair<int, string> >:: iterator p;
pair<int, string> p3;
for(p = lines.begin(); p != lines.end(); p++){
p3 = p->second;
// if line with that label already exists - do nothing
if(p->first == n1 && p3.first == n2 && p3.second == arrow_label) return;
}
// line n1 -> n2, arrow_label has not been found
lines.insert(pair<int, pair<int, string> >(n1, pair<int, string>(n2, arrow_label)));
}
//--- print json for Graph objects
void print_graph_json(){
JSON<< endl<< "{\"GRAPH\":["<< "\""<< title<< "\",";
char comma = ' ';
// print node list
JSON<< "\n [";
for(int i = 0; i < nodes.size(); i++){
JSON<< comma<< "["<< i <<", \""<< nodes[i] <<"\"] ";
comma = ',';
}
JSON<< "],";
// print arrow list
comma = ' ';
JSON<< "\n [";
multimap<int, pair<int, string> >::iterator p2;
for(p2 = arrows.begin(); p2 != arrows.end(); p2++){
JSON<< comma<< "["<< p2->first << ','<<(p2->second).first << ",\""<<
(p2->second).second << "\"]";
comma = ',';
}
JSON<< "],";
// print line list
comma = ' ';
JSON<< "\n [";
for(p2 = lines.begin(); p2 != lines.end(); p2++){
JSON<< comma<< "["<< p2->first << ','<<(p2->second).first << ",\""<<
(p2->second).second << "\"]";
comma = ',';
}
JSON<< "] ]}";
}
};// end graph_object class
//====================================================================
template <class tuple_class> class table_object {
public:
string title;
vector <tuple_class> table_contents;
// constructor
table_object(){ title = " "; }
void clean(){
table_contents.clear();
}
//--- print json for Table objects
void print_table_json(){
/*
JSON<< endl<< "{\"REPORT\":["<< "\""<< title<< "\"";
vector<string>::iterator p;
for(p = report_contents.begin(); p != report_contents.end(); p++){
JSON<<",\"" << *p<< "\"";
}
JSON<<"]}"<< endl;
*/
}
}; // end table_object class
/*
* mp2.h
*
* Created by Mike Auguston on 02/02/15
* recursive descent trace generation
* declarations and globals
*
* last modified: 02/08/19
*/
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
ofstream JSON; // text file for trace visualization
#include "global_objects.h" // to make JSON visible for global_view objects
//************************
//***** Statistics
//************************
int total_events = 0; // total events stored
int total_segments = 0; // store total trace number
clock_t gen_start, gen_end; // for time measurement
double dif; // time interval
//************************
//***** Globals
//************************
//ofstream JSON; // text file for trace visualization
class Event_producer;
class Composite_producer;
typedef Event_producer * Event_producer_ref;
typedef Composite_producer * Composite_producer_ref;
typedef vector <Event_producer_ref> trace_segment;
//***************************************
//*** these are used for traverse() work
//***************************************
trace_segment Stack;
// Stack used by producers for trace segment construction via traverse()
// to maintain relations lists
typedef multimap <int, int> pair_list;
// for storing basic relations IN, FOLLOWS, EQUAL, UDR for the segment,
// matricies for segments are build from these when needed
pair_list Follows; // to store FOLLOWS
pair_list Inside; // to store IN
pair_list Equals; // to store Equals (result of SHARE ALL)
//******* UDR infrasructure *************
typedef map <string, pair_list> UDR_set; // to store UDRs with the trace segment
// pair_list my_relation_UDR_set;
// for each UDR is generated before #include "mp2_print_etc.h"
UDR_set UDRs; // to prepare all UDRs for a segment before storing them
// in the segment storage by Composite_producer::harvest()
// for use in make_equality_complete(), the body is generated in .cpp
void merge_UDRs_for_shared_events(int a, int b);
//****** attribute table infrastructure ******
//=============================================
map<string, map<int, float> > number_attr_container;
map<string, map<int, bool> > bool_attr_container;
map<string, map<int, Interval> > interval_attr_container;
// this function is used in make_equality_complete()
bool shared_event_attribute_comparison (int event1, int event2);
vector <Interval> time_start_attributes,
time_duration_attributes,
time_end_attributes;
// this flag optimizes recalculate_timing_attributes() calls
// call only when true
bool timing_is_up_to_date = false;
// pre-defined attribute value
// maintained in Composit_producer:: harvest() within mp2_print_etc.h
int trace_id_attribute = 0;
//****** VIEW object infrastructure for trace list ******
//=======================================================
bool global_flag; // GLOBAL section is present
void harvest_GLOBAL_view(Composite_producer *);
typedef map<int, report_object> report_set;
report_set report_container; // container for a single trace, holds all reports
vector<report_set> report_list; // list for traces
typedef map<int, graph_object> graph_set;
graph_set graph_container; // container for a single trace, holds all graphs
vector<graph_set> graph_list; // list for traces
typedef set<string> AD_flag_set;
AD_flag_set AD_flags; // to hold ADs requested for this trace
vector <AD_flag_set> AD_flag_list; // list for traces
char Mark; // 'M' for MARKed trace, 'U' for unMARKed
// stack accompanying the Stack
vector <int> predecessor; // to track PRECEDES relation during traverse()
// push/pop performed in Composite_producer
// root table supporting 'FROM root' clauses in COORDINATE,
// SHARE ALL and special_operation '#a FROM root'
// holds pairs (root_event_name, position_in_Stack)
// maintained in Composite_secondary_producer::traverse()
// the (root_name, position) is updated each time when a root segment is placed in the Stack
// used in generated traverse() for coordinate, share_all and special_function
map <int, int> Root_table;
// messages produced by SAY, to avoid duplication,
// especially for constant message texts
class SAY_event;
map <string, SAY_event *> message_table;
// for calculating the probabilty of the segment under assembly
// used/modified in
// Composite_producer:: harvest(), initialized to 1.0 here,
// and prorated after all segments have been generated
// OR_node_producer_container:: traverse()
// Composite_secondary_producer:: traverse()
float segment_probability; // 0..1 range
//===========================
// for SET_node traverse()
//--------------------------------------------------
// initialized in Composite_producer, similar to predecessor.back()
// used in SET_node_producer_container
// replace predecessor when traversing Sets
// heads and tails store for each Set a list
// (branch_begin FOLLOWS node) for heads
// (forthcoming_node FOLLOWS end-of-branch-event) for tails
// each is a permanent list for Set traverse()
vector<pair_list> heads;
vector<pair_list> tails;
void find_and_copy_heads(int branch_start, int my_index);
void find_and_copy_tails(int first_branch_start, pair_list &destination);
void copy_from_to(int anchor, pair_list &from_list, pair_list &to_list);
void copy_and_adjust_from_to(int anchor, int adjusted_node,
pair_list &from_list, pair_list &to_list);
bool find_in_heads(int node);
//===================================
// composite producers infrastructure
//===================================
void add_relations_for_leader(); // the subroutine for adding relations for
//the leading event in Atomic_producer or Composite_secondary_producer
void add_adjusted_UDRs(int base,
UDR_set &UDR_list,
map<string, map<int, float> > &num_attr_container,
map<string, map<int, bool> > &bool_attr_container,
map<string, map<int, Interval> > &Interval_attr_container,
vector<Interval> &time_start_attributes,
vector<Interval> &time_duration_attributes,
vector<Interval> &time_end_attributes
);
// generated in the xxx.cpp file, contains all actual UDR and attribute tables
//==========================================================================
//********** main list of composite event, root, and schema producers ******
//==========================================================================
map <int, Composite_producer_ref> Composite_address_book;
// for each composite event/root/schema name contains a plain pointer to the
// producer object with the segment list
void show_map(pair_list &x);// for debugging printouts
//****************************
// event producer types
//****************************
enum Event_type {Atom, Composite_producer_node, Composite_event_instance_node,
Composite_secondary_producer_node,
ROOT_node, Schema_node, OR_node, AND_node, SET_node, Empty_node,
Coordinate_op, ShareAll_op, simple_or_IF_op, SAY_message };
string event_type_string[] = { "Atom", "Composite_producer_node",
"Composite_event_instance_node",
"Composite_secondary_producer_node",
"ROOT_node", "Schema_node",
"OR_node", "AND_node", "SET_node",
"Empty_node", "Coordinate_op", "ShareAll_op",
"simple_or_IF_op", "SAY_message" };
//======= traversal results
enum Traversal_result {failed, success_and_completed, success_and_ready_for_next};
string Traversal_result_string[] = {"failed", "success_and_completed",
"success_and_ready_for_next"};
//*****************************************************************
// for layout calculation in Composite_producer::output_JSON()
//*****************************************************************
// layout node structure for layout calculation in output_JSON()
struct layout_node {
int event_id; // unique event index in segments[kk]
Event_type type;
int column;
float fcol; // for calculating intermediate columns
// for shared and cincurrent events
int row;
};
// global declarations for layout calculation
// needed also to support recursion for proceed_with_column()
vector <layout_node> layout;
vector <int> available_row; // for each column
vector <char> is_global_event; // for marking global SAY events
vector <int> latest_accepted; // latest accepted event_id in the column
// used to determine concurrency
int current_event; // index in layout for event under processing
int first_available_column;
//================================================
// for coordination source permutation management
// to mark the end of derivation path in Atomic_producer,
// Composite_event_instance, Coordination_source
//-----------------------------------------------------
// global path mark, on backtracking to check wheteher the path
// is still the same. Is set with a unique_number by Atomic_producer,
// Composite_secondary_producer, and in generated Coordinate class
// appearing at the end of derivation path
int derivation_path_mark; // initialized in the generated main()
int unique_num; // for use in Atomic_producer,
// Composite_secondary_producer, generated Coordinate class
// initialized in the generated main()
int get_unique_number(){
unique_num++;
return unique_num;
}
// Coordination_source objects are used for generating permutations of the
// default event set
//=======================================================
class Coordination_source {
public:
vector<int> work; // current permutation at work
bool hold; // hold previous permutation
bool was_on_hold; // to prevent from reset() on following Coordination_sources
int total; // total number of permutations completed
int total_max; // N!, where N == work().size()
Traversal_result previous_Traversal_result;
// constructor
Coordination_source (){
hold = false;
was_on_hold = false;
total = 0;
total_max = 0;
previous_Traversal_result = failed;
}
void reset(){
// reset to start new permutation cycle
hold = false;
was_on_hold = false;
total = 0;
total_max = 0;
work.clear();
}
Traversal_result get_permutation(vector<int> &result){
if(result.size() < 2) {
previous_Traversal_result = success_and_completed;
total = total_max = 1;
if(hold) {
hold = false;
was_on_hold = true;
}
else was_on_hold = false;
work = result;
return success_and_completed;
}
if(hold){ // do nothing, return previous Traversal_result and work
result = work;
hold = false;
was_on_hold = true;
return previous_Traversal_result;
}
else { // no hold
switch(previous_Traversal_result){
case success_and_completed:
case failed: // this case is taken at the initial call only
reset();
work = result;
// recalculate N!
total_max = 1;
for(int i = 1; i <= result.size(); i++) total_max *= i;
sort(work.begin(), work.end());// required by next_permutation()
break;
case success_and_ready_for_next: was_on_hold = false;
// and proceed with the next permutation
} // end switch
}// end else - ! hold
if( next_permutation(work.begin(), work.end())) {
result = work;
total++;
if (total == total_max){
// hold, was_on_hold have been set in the if(hold) before
return (previous_Traversal_result = success_and_completed);
}
else {
// hold, was_on_hold have been set in the if(hold) before
return (previous_Traversal_result = success_and_ready_for_next);
}
}
else { // next permutation does not exist, work is sorted, return it
result = work;
total = total_max;
if(hold) {
hold = false;
was_on_hold = true;
}
else was_on_hold = false;
return (previous_Traversal_result = success_and_completed);
}
} // end get_permutation()
void hold_source(){
hold = true;
}
}; // end of class Coordination_source
//------------------------------------------------------
//**************************************
//========= generic classes ============
//**************************************
//********** Event producers ************
//***************************************
class Event_producer{
public:
int name; // event name
Event_type type;
// constructor
Event_producer(int n){
name = n;
type = Atom; // default
}
virtual Traversal_result traverse()=0; // will be overloaded
virtual void hold(){
} // redefined for OR_, AND_, SET_, COORDINATE_event nodes
virtual void print_event();
};
//--------------------------------------
class Atomic_producer: public Event_producer {
public:
int unique_id;
// constructor
Atomic_producer(int n): Event_producer(n){
unique_id = get_unique_number();
}
Traversal_result traverse(){
// add relations for new event
add_relations_for_leader();
Stack.push_back(this);
// add timing attributes for this event, initialized by [0..0]
time_start_attributes.push_back(Interval());
time_duration_attributes.push_back(Interval());
time_end_attributes.push_back(Interval());
derivation_path_mark = unique_id;
return success_and_completed;
}
};// end class Atomic_producer
//-----------------------------------------
// empty alternative in Alt and Optional containers
// does not leave anything on the trace
class Empty_producer: public Event_producer {
public:
// constructor
Empty_producer(int n): Event_producer(n){
type = Empty_node;
}
Traversal_result traverse(){
return success_and_completed;
}
};// end class Empty_producer
//-----------------------------------------
// SAY message event, usually IN composite, root, or schema box
class SAY_event: public Event_producer {
public:
string message;
// constructor
SAY_event(int n, string msg): Event_producer(n){
type = SAY_message;
message = msg;
}
void print_event(); // defined in the generated part,
// because it needs event type and name strings
// to prevent this class from being abstract, as Event_producer
Traversal_result traverse(){return success_and_completed;}
};// end class SAY_event
//-----------------------------------------
class OR_node_producer_container: public Event_producer{
public:
Event_producer_ref * element; // dynamic array of producer elements
int element_count; // length of the element array
int current_alternative; // the alternative to try, when there is one
int previous_alternative; // to hold on the alternative waiting until successors complete
float * alternative_probability; // dynamic array storing probability for each alternative
// allocated/initialized in the generated in the generated constructors
// for Alt_nnn classes in .cpp file
// constructor
OR_node_producer_container(int n): Event_producer(n){
type = OR_node;
current_alternative = 0;
}
Traversal_result traverse(){
previous_alternative = current_alternative;
Traversal_result result;
bool done = false; // to interrupt the for loop when success is reached
// try to find a valid alternative
int successful_alternative;
for(int i = current_alternative; (i < element_count) && !done; i++){
switch(result = (element[i] -> traverse()) ){
case failed: continue; // try next alternative
case success_and_completed: current_alternative++;
done = true;
successful_alternative = i;
break;
case success_and_ready_for_next: done = true;
successful_alternative = i;
// retain the current_alternative
};
}
if(result == failed) return failed;
// if success, multiply by the probability of alternative used
segment_probability *= alternative_probability[successful_alternative];
return (current_alternative >= element_count)?
(current_alternative = 0, success_and_completed):
success_and_ready_for_next;
}
virtual void hold(){ //follower in an AND_node may hold advance to the next alternative
// because the follower has not yet completed
current_alternative = previous_alternative;
// freez producers in the alternative that will be executed next
element[current_alternative]->hold();
}
}; // end OR_node_producer_container class
//-----------------------------------------------------------
class AND_node_producer_container: public Event_producer{
// serves sequence producers
public:
Event_producer_ref * element; // array of producer elements
int element_count; // length of the element array
Event_type target_event;// set in the generated subclass constructor
int completeness_count; // for traverse() to detect when no more options remain
// constructor
AND_node_producer_container(int n): Event_producer(n){
type = target_event = AND_node;
}
Traversal_result traverse(){
completeness_count = 0;
for(int i =0; i< element_count; i++){
if(target_event == Schema_node) {
// before element[i] -> traverse()
predecessor.back() = -1; // block regular ordering
}
switch(element[i] -> traverse()){
case failed: if(completeness_count == i)
// there are no more options to try
// let harvest() to stop calling this traverse() again
completeness_count = element_count;
return failed;
case success_and_completed: completeness_count++;
break;
case success_and_ready_for_next:
// hold all previous nodes until element[i] completes
for(int j = 0; j<i; j++)
element[j]->hold();
};
}
return (completeness_count == element_count)? success_and_completed:
success_and_ready_for_next;
}
virtual void hold(){
// hold all nodes until next element completes
for(int j = 0; j < element_count; j++){
element[j]->hold();
}
}
}; // end AND_node_producer_container class
//----------------------------------------------------------------------
class SET_node_producer_container: public Event_producer{
// serves set producers
public:
Event_producer_ref * element; // array of producer elements
// set branches
int element_count; // length of the element array
// constructor
SET_node_producer_container(int n): Event_producer(n){
type = SET_node;
}
Traversal_result traverse(){
int completeness_count = 0;
//========= begin Set traversal ================
// prepare heads for set branch traversal
//==============================================
int last = predecessor.back(); // current predecessor, value stored on the top of stack
int first_branch_start = Stack.size();
pair_list temp_list; // needed to push empty map to heads,
// and to store this Set's tails before moving them to global tails
set<int> my_tails; // will use in this traverse() and store in tails at the very end
int empty_elt_num = 0; // number of empty traversals, if all of them were empty,
// then event after set should FOLLOW the 'last' event
int my_index = heads.size(); // position in heads vector
heads.push_back(temp_list); // start heads[my_index] with empty, will update in situ
// prepare heads for the first branch
if(last >= 0){
// this Set is not at any branch begin in a parent Set
heads[my_index].insert(pair<int, int>(first_branch_start, last) );
}
// find the earliest parent and copy to heads[my_index] for this branch
// this Set is at some branch beginning with a parent Set
find_and_copy_heads(first_branch_start, my_index);
// if first_branch_start is found in any previous Set tails, copy it to heads[my_index]
find_and_copy_tails(first_branch_start, heads[my_index]);
//============================
// main loop starts here
//============================
for(int i =0; i< element_count ; i++){
//=================================
// before element[i] -> traverse()
//=================================
predecessor.back() = -1; // block regular ordering
int forthcoming_event = Stack.size();
if(forthcoming_event > first_branch_start){
// not the first branch beginning, copy and adjust
copy_and_adjust_from_to(first_branch_start, forthcoming_event,
heads[my_index], heads[my_index]);
}
// copy tails from children Set and delete them, to prevent siblings from using it
for(int k = 0; k < tails.size(); k++){
multimap<int, int>:: iterator p = tails[k].find(forthcoming_event);
multimap<int, int>:: iterator q = tails[k].upper_bound(forthcoming_event);
if(p != tails[k].end()){ // found a tail that should be added to my_tails
while(p != q) {
my_tails.insert(p->second);
p++;
}
tails[k].clear();// done with this Set
}
}
//===============
// traverse()
//===============
switch(element[i] -> traverse()){
case failed: return failed;
case success_and_completed: completeness_count++;
break;
case success_and_ready_for_next:
// hold all previous OR_nodes until element[i] completes
for(int j = 0; j<i; j++)
element[j]->hold();
}
//===============================
// after element[i] -> traverse()
//===============================
int next_event = Stack.size();
if( next_event > forthcoming_event ){
// there was a non-empty contribution by traverse()
// forthcoming_event exists, now can forward heads[my_index]
// for forthcoming_event to Follows
// and perform this delayed action
copy_from_to(forthcoming_event, heads[my_index], Follows);
if(predecessor.back() >= 0){
my_tails.insert(predecessor.back());
}
}
else { // traverse is empty
empty_elt_num++;
}
// continue element[i+1] -> traverse() with the same heads and tails
} // end main loop
// after the last element
// copy tails from children Set
int next_ev = Stack.size();
for(int k = 0; k < tails.size(); k++){
multimap<int, int>:: iterator p = tails[k].find(next_ev);
multimap<int, int>:: iterator q = tails[k].upper_bound(next_ev);
if(p != tails[k].end()){ // found a tail that should be added to my_tails
while(p != q) {
my_tails.insert(p->second);
p++;
}
tails[k].clear();// done with this Set
}
}
if((empty_elt_num == element_count) && (last >= 0)) {
// if all traversed elements are empty and if predecessor is defined
// add 'last' to the my_tails to ensure that event after the set FOLLOWS it
// 'last' is the value stored on the top of stack
my_tails.insert(last);
}
//============================
// end of Set generation
//============================
// store tails accumulated in my_tails
int next = Stack.size();
for(set<int>:: iterator tt = my_tails.begin(); tt != my_tails.end(); tt++){
temp_list.insert(pair<int, int>(next, *tt) );
}
// finally add to the global tails
tails.push_back(temp_list);
predecessor.back() = -1; // block regular ordering
return (completeness_count == element_count)? success_and_completed:
success_and_ready_for_next;
}
void hold(){
// hold all nodes until next element completes
for(int j = 0; j < element_count; j++){
element[j]->hold();
}
}
}; // end SET_node_producer_container class
//--------------------------------------------------
// this element sits on the generated event trace, along with Atom generated by Atomic_producers.
// is generated in the Composite_secondary_producer,
// added at the beginning of each segment,
// brought from the Composite_producer segments storage
class Composite_event_instance: public Event_producer{
public:
int index; // fetched segment's index in the segment_storage (version of this composite event)
// constructor
Composite_event_instance(int n, int indx): Event_producer(n){
type = Composite_event_instance_node;
index = indx;
}
void print_event(); // defined in the generated part,
// because it needs event type and name strings
// to prevent this class from being abstract, as Event_producer
Traversal_result traverse(){return success_and_completed;}
}; // end Composite_event_instance class
//---------------------------------------------------------------
// is a subclass of generated Composite classes
// this object creates and stores list of composite event instances
// traverse() is called from its harvest() only
class Composite_producer: public AND_node_producer_container {
public:
// storage for secondary producers
//===================================
vector <trace_segment> segments;// composite event trace instance list
// lists to store relation tables for the segments
vector <pair_list> follows_lists; // to store FOLLOWS
vector <pair_list> inside_lists; // to store IN
vector <pair_list> equals_lists; // to store Equals (results of MAP or SHARE ALL)
vector <UDR_set> UDR_lists; // to store UDRs
// to store attribute tables for segments
vector < map<string, map<int, float> > > float_attribute_lists;
vector < map<string, map<int, bool> > > bool_attribute_lists;
vector < map<string, map<int, Interval> > > interval_attribute_lists;
vector < vector <Interval> > start_attribute_list,
duration_attribute_list,
end_attribute_list;
vector <char> MARK_list; // for each segment stores 'U' or 'M'
vector <float> probability_list; // probability for each generated segment
// obtained from
// OR_node_producer_container:: traverse()
// Composite_secondary_producer:: traverse()
// prorated at the end of Composite_producer:: harvest()
// constructor
Composite_producer(int n): AND_node_producer_container(n){
type = Composite_producer_node;
// posts a reference to itself on the Composite_address_book
Composite_address_book.insert(pair<int, Composite_producer_ref>(name, this));
}
Traversal_result traverse(){
// creates a single trace on the Stack
return this -> AND_node_producer_container::traverse();
}
// calls traverse to fill the segments list
void harvest(); // defined in mp2_print_etc.h
void show_traces(); // defined in mp2_print_etc.h
void output_JSON(); // defined in mp2_print_etc.h
}; // end Composite_producer class
//-------------------------------------------------------
// sits in the recursive descent graph
// used during the recursive descent to traverse composite storage
// and to fetch the next composite segment
// previous_index shows the position of segment added to the trace
class Composite_secondary_producer: public Event_producer{
public:
Composite_producer_ref segment_storage;// ptr to segment info stored in Composite_producer
int index; // segment info index in the segment_storage to fetch now
int previous_index; // for hold() implementation
int unique_id;// for marking the path end
// constructor
Composite_secondary_producer(int n): Event_producer(n){
type = Composite_secondary_producer_node;
// find segment list storage
map <int, Composite_producer_ref> :: iterator p;
p = Composite_address_book.find(name);
if(p == Composite_address_book.end()){
cout<< "Composite_secondary_producer constructor cannot find segment storage for the\n";
print_event();
segment_storage = NULL;
}
else segment_storage = p-> second;
index = 0;
previous_index = 0;
unique_id = get_unique_number();
}
Traversal_result traverse(){
// to keep path marker unique for each version of this composite
// assuming that total number of events will not exceed 100000
derivation_path_mark = unique_id + 100000 * index;
if(!segment_storage) {
// add relations for new event and add it
add_relations_for_leader();
Stack.push_back(new Composite_event_instance(name, 0));
// add timing attributes for this event, initialized by [0..0]
time_start_attributes.push_back(Interval());
time_duration_attributes.push_back(Interval());
time_end_attributes.push_back(Interval());
return success_and_completed;
}
// we are going to fetch this segment from the storage
trace_segment * my_segment_ptr = & ((segment_storage->segments)[index]);
// prepare for added segment scanning for relation update
int base = Stack.size(); //master Composite_event_instance event's position in the trace
// base is the position of composite event inside which the segment belongs
// if type is ROOT_node, store base in the Root_table
// for schema's name Root_table[name] always will produce position 0
if (type == ROOT_node) Root_table[name] = base;
// fetch a valid alternative and adjust relation list
add_relations_for_leader();// add IN/PRECEDES for the composite event at the beginning of segment
// finally, bring in the Stack body of this composite from the segment
Stack.insert(Stack.end(), my_segment_ptr->begin(), my_segment_ptr->end() );
// get the relation lists from the storage, adjust them with base,
// and add to Follows, Inside, Equals, and UDRs
multimap <int, int>:: iterator p;
pair_list * my_rel_list_ptr = & ((segment_storage->follows_lists)[index]);
for(p = my_rel_list_ptr-> begin(); p != my_rel_list_ptr-> end(); p++){
// scan the list of pairs and add them to Follows adjusted with base
Follows.insert(pair<int, int>( (p->first) + base,
(p->second) + base ) );
}
my_rel_list_ptr = & ((segment_storage->inside_lists)[index]);
for(p = my_rel_list_ptr-> begin(); p != my_rel_list_ptr-> end(); p++){
// scan the list of pairs and add them to Follows adjusted with base
Inside.insert(pair<int, int>( (p->first) + base,
(p->second) + base ) );
}
my_rel_list_ptr = & ((segment_storage->equals_lists)[index]);
for(p = my_rel_list_ptr-> begin(); p != my_rel_list_ptr-> end(); p++){
// scan the list of pairs and add them to Follows adjusted with base
Equals.insert(pair<int, int>( (p->first) + base,
(p->second) + base ) );
}
// scan the UDRs, if any, adjust/add them to the current xxx_UDR_set
// add to each generated in .cpp file xxx_UDR_set all pairs adjusted with base each
// and bring the original timing attributes into the segment
// subroutine void add_adjusted_UDRs(int base, UDR_set & UDR_list) is generated in .cpp file
add_adjusted_UDRs( base,
(segment_storage->UDR_lists)[index],
(segment_storage->float_attribute_lists)[index],
(segment_storage->bool_attribute_lists)[index],
(segment_storage->interval_attribute_lists)[index],
(segment_storage->start_attribute_list)[index],
(segment_storage->duration_attribute_list)[index],
(segment_storage->end_attribute_list)[index] );
// check if fetched segment is MARKed,
// if so, propagate Mark for the segment under assembly
if( ((segment_storage->MARK_list)[index]) == 'M') Mark = 'M';
previous_index = index;
// pick up the probability of segment and multiply the global segment_probability by it
segment_probability *= (segment_storage-> probability_list)[index];
// prepare for timing attribute re-calculations when needed
timing_is_up_to_date = false;
index++;
return (index >= (segment_storage->segments).size() )?
(index = 0, success_and_completed):
success_and_ready_for_next;
}
void hold(){
//follower in an AND_node may hold advance to the next alternative
// because the follower has not yet completed
index = previous_index;
}
}; // end Composite_secondary_producer class
//---------------------------------------------------------------------------
class Coordinate: public Event_producer {
public:
// these arrays are 2-dimensional,
// and are allocated/deleted in generated traverse()
// by create_matrices() as Stack.size() * Stack.size()
char * eq_matrix;
char * in_matrix;
char * follows_matrix;
int len; // matrix dimension
int matrix_len; // len * len
Coordinate * current_host; // for use in special function and quantified expr
// constructor
Coordinate(int n): Event_producer(n){
type = Coordinate_op;
eq_matrix = in_matrix = follows_matrix = 0;
len = matrix_len = 0;
current_host = this;
}
// transitive closures are based on Floyd-Warshall algorithm
// [Cormen et al. 3rd Edition, pp.699]
//--------------------------------------------------------------
void eq_transitive_closure(char * m){
for(int k = 0; k < len; k++){
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
m[i * len + j] =
m[i * len + j] || (m[i * len + k] && m[k * len + j]);
}
}
}
} // end eq_transitive_closure(char * m)
void in_transitive_closure(char * m){
// merge equal event rows
for(int i = 0; i < len; i++){
for(int j = i + 1; j < len; j++){
if(eq_matrix[i * len + j]){
for(int k = 0; k < len; k++){
m[i * len + k] =
m[j * len + k] =
m[i * len + k] || m[j * len + k];
}
}
}
}
// do the closure
for(int k = 0; k < len; k++){
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
m[i * len + j] =
m[i * len + j] || (m[i * len + k] && m[k * len + j]);
}
}
}
// check for loops: axioms 5-6
for(int i = 0; i < len; i++){
if(m[i * len + i]) throw failed;
}
} // end in_transitive_closure(char * m)
void fw_transitive_closure(char * m){
// merge equal event rows
for(int i = 0; i < len; i++){
for(int j = i + 1; j < len; j++){
if(eq_matrix[i * len + j]){
for(int k = 0; k < len; k++){
m[i * len + k] =
m[j * len + k] =
m[i * len + k] || m[j * len + k];
}
}
}
}
// propagate FOLLOWS to the inner events
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
// distributivity axioms 9-10
if(in_matrix[i * len + j]){
for(int k = 0; k < len; k++){
m[k * len + i] =
m[k * len + i] || m[k * len + j];
}
for(int k = 0; k < len; k++){
m[i * len + k] =
m[i * len + k] || m[j * len + k];
}
}
}
}
// do the closure
for(int k = 0; k < len; k++){
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
m[i * len + j] =
m[i * len + j] || (m[i * len + k] && m[k * len + j]);
}
}
}
// check for loops: axioms 5-6
for(int i = 0; i < len; i++){
if(m[i * len + i]) throw failed;
}
// check for mutual exclusion: axioms 1-4
for(int k = 0; k < len; k++){
for(int i = 0; i < len; i++){
if(in_matrix[k * len + i] &&
follows_matrix[k * len + i]) throw failed;
}
}
} // end fw_transitive_closure(char * m)
void delete_matrices(){
if(in_matrix){
delete [] eq_matrix;
delete [] in_matrix;
delete [] follows_matrix;
eq_matrix = in_matrix = follows_matrix = 0;
len = 0;
}
}
void create_matrices(){
delete_matrices(); // in case if Stack has been modified between calls
len = Stack.size();
matrix_len = len * len;
// allocate and initialize with 0
eq_matrix = new char [matrix_len];
in_matrix = new char [matrix_len];
follows_matrix = new char [matrix_len];
for(int i = 0; i < matrix_len; i++){
eq_matrix[i] =
in_matrix[i] =
follows_matrix[i] = 0;
}
multimap <int, int>:: iterator p;
// fill eq matrix
for(p = Equals.begin(); p != Equals.end(); p++){
eq_matrix[p->first * len + p->second ] =
eq_matrix[p->second * len + p->first ] = 1;
}
eq_transitive_closure(eq_matrix);
// fill in matrix
for(p = Inside.begin(); p != Inside.end(); p++){
in_matrix[p->first * len + p->second ] = 1;
}
in_transitive_closure(in_matrix);
// fill follows matrix
for(p = Follows.begin(); p != Follows.end(); p++){
follows_matrix[p->first * len + p->second ] = 1;
}
fw_transitive_closure(follows_matrix);
} // end create_matrices()
void sort_events(vector<int> &L){
// sorts vector of events by FOLLOWS
// Selection Sort, Levitin p.99 (OK for small lists)
// although selection sort is not stable
if(L.size() < 2) return;
int min, temp;
for(int i = 0; i < L.size() - 1; i++){
min = i;
for(int j = i + 1; j < L.size(); j++){
if(follows_matrix[L[min] * len + L[j]]){
min = j;
}
}
temp = L[i];
L[i] = L[min];
L[min] = temp;
}
}
void sort_and_check_coordinated_events(vector<int> &L){
// for synchronous COORDINATE
// sorts vector of events by FOLLOWS
// then checks for total ordering
if(L.size() < 2) return;
sort_events(L);
// check total ordering
for(int i = 0; i < L.size() - 1; i++){
if(!follows_matrix[L[i + 1] * len + L[i]]) throw failed;
}
}
void topological_sort(vector<int> &L){
if(L.size() < 2) return;
if(!follows_matrix) create_matrices();
// make a copy of follows_matrix
int total_len = len * len;
char m[total_len];
for(int i = 0; i < total_len; i++ ){
m[i] = follows_matrix[i];
};
int Lsize = L.size();
int found;
vector<int> result;
result.reserve(Lsize);
// to keep track about events already put in the result
char already_there[len];
for(int i = 0; i < len; i++){
already_there[i] = 0;
}
while(result.size() < Lsize) {
for(int i = 0; i < Lsize; i++){
if( !already_there[L[i]] ){
// L[i] is not there yet
// traverse follows_matrix[L[i]] row, searching for incoming arrows
found = 0;
for(int j = 0; j < Lsize; j++){
found += m[L[i] * len + L[j]];
};
if(!found) {
// L[i] does not have incoming arrows from L
result.push_back(L[i]);
already_there[L[i]] = 1;
// remove L[i] from the matrix m
for(int k = 0; k < len; k++){
m[k * len + L[i]] = 0;
}
}
}
}
};
L = result;
}
void make_equality_complete(int a, int b){
// add to Equals, but earlier position in Stack is more equal :-)
// copies all Follows and Inside from b to a
// and do the same for all inner events
if(a == b) return;
if(Stack[a]->name != Stack[b]->name) throw failed;
if(Stack[a]->type == Composite_event_instance_node &&
Stack[b]->type == Composite_event_instance_node &&
( ((Composite_event_instance *)Stack[a])->index !=
((Composite_event_instance *)Stack[b])->index ) )throw failed;
// check whether a and b have the same set of attribute values, if not - fail
// shared_event_attribute_comparison() is generated in .cpp after attribute sets
if (!shared_event_attribute_comparison(a, b)) throw failed;
// earlier position in Stack is more equal :-)
if(a > b) {int t = a; a = b; b = t;}