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