1 
2 /* Web Polygraph       http://www.web-polygraph.org/
3  * Copyright 2003-2011 The Measurement Factory
4  * Licensed under the Apache License, Version 2.0 */
5 
6 #ifndef POLYGRAPH__PGL_PGLARRAYSYM_H
7 #define POLYGRAPH__PGL_PGLARRAYSYM_H
8 
9 #include <vector>
10 #include "xstd/Array.h"
11 #include "pgl/PglContainerSym.h"
12 
13 class RndDistr;
14 class String;
15 
16 // array of PglArrayItems with optional probabilities
17 class ArraySym: public ContainerSym {
18 	public:
19 		static String TheType;
20 
21 	public:
22 		ArraySym();
23 		ArraySym(const String &anItemType);
24 		virtual ~ArraySym();
25 
26 		virtual bool isA(const String &type) const;
27 
28 		virtual bool empty() const;
29 		virtual int count() const;
30 		virtual bool probsSet() const;
31 		virtual const SynSym *itemProb(int offset, double &prob) const;
32 
33 		virtual const SynSym *item(int idx) const;
34 		double prob(int idx) const;
35 
36 		void reserve(int minCount);
37 		void add(const SynSym &s, double prob = -1);
38 		bool cadd(const SynSym &s, double prob = -1);
39 		bool append(const ArraySym &arr);
40 
41 		// flattens and exports Items
42 		template <class Item>
43 		int exportA(Array<Item*> &arr) const;
44 
45 		// exports Arrays of Items
46 		template <class Item>
47 		bool exportNestedArrays(std::vector< std::vector<Item*> > &arr) const;
48 
49 		// rnd distr of array idxes that matches item probabilities
50 		RndDistr *makeSelector(const String &name);
51 		void copyProbs(Array<double> &res) const;
52 
53 		virtual void forEach(Visitor &v, RndGen *const rng = 0) const;
54 
55 		virtual ExpressionSym *bnOper(const Oper &op, const SynSym &exp) const;
56 
57 		virtual ostream &print(ostream &os, const String &pfx) const;
58 
59 	protected:
60 		virtual SynSym *dupe(const String &dType) const;
61 		virtual ArraySym *create(const String &itemType) const;
62 
63 		int itemCountAt(int idx) const;
64 		bool itemProbsSetAt(int idx) const;
65 		const SynSym *itemProbAt(int idx, int offset, double &prob) const;
66 
67 		double actualProb(double p) const;
68 		double explProb(int firstLevelOff) const;
69 
70 		// a helper for the exportNestedArrays() template; does no type casting
71 		static bool GetNestedArraysFromItem(Array<const ArraySym*> &arrays, const SynSym *item);
72 
73 	protected:
74 		Array<SynSym*> theItems;   // array [top-level] members
75 		const String theItemType;  // set when known
76 
77 		Array<double> theProbs;     // explicit probs for each item
78 		bool nested; // this array contains other containers
79 		mutable bool warnedBadProbs;
80 };
81 
82 
83 /* template to transform array symbol into arrays of symbols/items
84  * the only reason to use a template is to avoid a[i] casting
85  * think: maybe the array symbol should be a template instead?? */
86 template <class Item>
exportA(Array<Item * > & arr)87 int ArraySym::exportA(Array<Item*> &arr) const {
88 	arr.stretch(count());
89 	for (int i = 0; i < count(); ++i) {
90 		Item *const item = &((Item&)(*this)[i]->cast(Item::TheType));
91 		arr.append(item);
92 	}
93 	return arr.count();
94 }
95 
96 template <class Item>
exportNestedArrays(std::vector<std::vector<Item * >> & arr)97 bool ArraySym::exportNestedArrays(std::vector< std::vector<Item*> > &arr) const {
98 	if (!nested)
99 		return false;
100 
101 	Array<const ArraySym*> arrays;
102 	for (int i = 0; i < theItems.count(); ++i) {
103 		if (!GetNestedArraysFromItem(arrays, theItems[i]))
104 			return false;
105 	}
106 
107 	arr.resize(arrays.count());
108 	for (int i = 0; i < arrays.count(); ++i) {
109 		const ArraySym &a = *arrays[i];
110 		arr[i].resize(a.count());
111 		for (int j = 0; j < a.count(); ++j) {
112 			Item *const item = &((Item&)a[j]->cast(Item::TheType));
113 			arr[i][j] = item;
114 		}
115 	}
116 	return true;
117 }
118 
119 #endif
120