Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

216
LINES

< > BotCompany Repo | #1031504 // ProbabilisticList - list ordered by probability [OK!]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (10590L/59K).

1  
// As long as you don't access the by-numeral-index functions,
2  
// you can add and remove elements quickly.
3  
// Upon accessing the list, it is updated once to fit the new data.
4  
5  
// Note: When adding the same element twice, it will be stored only
6  
//       once with the higher probabilities of the two.
7  
//
8  
// class is synchronized
9  
sclass ProbabilisticList<A> extends AbstractRandomAccessList<WithProbability<A>> {
10  
  // these are the 2 main data structures we update
11  
  Map<A, Double> probabilities = hashMap();
12  
  MultiSetMap<Double, A> byProbability
13  
    = multiSetMap_outerDescTreeMap_innerCompactLinkedHashSet();
14  
    // = multiSetMap_outerDescTreeMap_innerBetterLinkedHashSet();
15  
  
16  
  L<WithProbability<A>> list; // this is only updated when requested
17  
  
18  
  // CUSTOMIZATION
19  
  
20  
  // must be >= 0. probability 0 is never added
21  
  double cutoffProbabilityOnAdd = 0;
22  
  
23  
  Cl<ProbabilisticListListener<A>> listeners;
24  
  
25  
  *() {}
26  
  *(Iterable<WithProbability<A>> l) {
27  
    main addAll(this, l);
28  
  }
29  
  
30  
  public synchronized WithProbability<A> get(int idx) {
31  
    if (idx < 0 || idx >= size()) null;
32  
    makeListUpToIndex(idx);
33  
    ret list.get(idx);
34  
  }
35  
  
36  
  public synchronized int size() { ret l(probabilities); }
37  
  
38  
  // assuming the index is within range
39  
  void makeListUpToIndex(int idx) {
40  
    if (idx < l(list)) ret; // index already there
41  
    
42  
    if (list == null) list = new L;
43  
    
44  
    WithProbability<A> lastEntry = main last(list);
45  
    A a = lastEntry?!;
46  
    double probability = lastEntry == null ? 0 : lastEntry.probability();
47  
    
48  
    //print("Making list from " + l(list) + " to " + idx);
49  
    
50  
    while (idx >= l(list)) {
51  
      //printVars_str(+idx, +a, +probability);
52  
      if (a == null) {
53  
        probability = byProbability.firstKey();
54  
        a = first(byProbability.get(probability));
55  
      } else {
56  
        CompactLinkedHashSet<A> setForProbability = cast byProbability.get(probability);
57  
        a = setForProbability.nextElement(a);
58  
        //printVars_str(+probability, +setForProbability, +a);
59  
        if (a == null) {
60  
          probability = byProbability.higherKey(probability);
61  
          a = first(byProbability.get(probability));
62  
        }
63  
      }
64  
      list.add(WithProbability(probability, a));
65  
    }
66  
  }
67  
  
68  
  synchronized bool containsElement(A a) {
69  
    ret probabilities.containsKey(a);
70  
  }
71  
  
72  
  public bool add aka put(A a, double probability) {
73  
    ret add(WithProbability(probability, a));
74  
  }
75  
  
76  
  public bool add(WithProbability<A> wp) {
77  
    A a;
78  
    double newP;
79  
    
80  
    synchronized {
81  
      if (wp == null || wp.probability() <= cutoffProbabilityOnAdd) false;
82  
      a = wp!;
83  
      newP = wp.probability();
84  
      Double oldP = probabilities.get(a);
85  
      if (oldP != null) {
86  
        if (oldP.doubleValue() >= newP)
87  
          false;
88  
        else
89  
          remove(WithProbability<A>(oldP, a));
90  
      }
91  
        
92  
      clearListFrom(newP);
93  
      probabilities.put(a, newP);
94  
      byProbability.add(newP, a);
95  
    }
96  
      
97  
    fireElementAdded(a, newP);
98  
    true;
99  
  }
100  
  
101  
  // will also delete if given probability doesn't match
102  
  @Override
103  
  public bool remove(O wp) {
104  
    if (wp == null) false;
105  
    cast wp to WithProbability<A>;
106  
    ret removeElement(wp!);
107  
  }
108  
  
109  
  public synchronized bool removeElement(A a) {
110  
    if (a == null) false;
111  
    Double oldP = probabilities.get(a);
112  
    if (oldP == null) false;
113  
    clearListFrom(oldP);
114  
    probabilities.remove(a);
115  
    byProbability.remove(oldP, a);
116  
    true;
117  
  }
118  
  
119  
  @Override
120  
  public synchronized WithProbability<A> remove(int idx) {
121  
    var a = get(idx);
122  
    remove(a);
123  
    ret a;
124  
  }
125  
  
126  
  // internal
127  
  void clearListFrom(double p) {
128  
    int idx = generalizedBinarySearch2(list, a -> a.probability() <= p ? 1 : -1);
129  
    idx = -idx-1;
130  
    //printVars clearListFrom(p, idx, before := takeFirst(idx, list), after := main subList(idx, list));
131  
    truncateList(list, idx);
132  
  }
133  
  
134  
  void at(double p, A a) {
135  
    add(WithProbability(p, a));
136  
  }
137  
  
138  
  // faster version of truncateList
139  
  void truncate(int size) {
140  
    if (size < 0) fail();
141  
    while (size() > size)
142  
      removeLast();
143  
  }
144  
  
145  
  double getProbability(A a) {
146  
    ret orZero(probabilities.get(a));
147  
  }
148  
149  
  void truncateBelow(double thresholdProbability) {
150  
    A a;
151  
    while ((a = last()) != null && getProbability(a) < thresholdProbability)
152  
      removeElement(a);
153  
  }
154  
  
155  
  A last() {  
156  
    Double last = byProbability.lastKey();
157  
    if (last == null) null;
158  
    CompactLinkedHashSet<A> set = cast byProbability.getOpt(last);
159  
    ret set.last();
160  
  }
161  
  
162  
  void removeLast {
163  
    removeElement(last());
164  
  }
165  
  
166  
  int indexOfElement(A a) {
167  
    // quickly bail if element is not contained
168  
    double p = getProbability(a);
169  
    if (p == 0) ret -1;
170  
    
171  
    // TODO: binary search and stuff
172  
    int n = size();
173  
    for i to n:
174  
      if (eq(a, get(i)!))
175  
        ret i;
176  
    fail("Internal error");
177  
  }
178  
  
179  
  // elements without probabilities
180  
  L<A> rawList aka elementsOnly() {
181  
    ret lazyMap_noSave(this, a -> a!);
182  
  }
183  
  
184  
  // just the probabilities in the list
185  
  L<Double> probabilities() {
186  
    ret lazyMap_noSave(this, a -> a.probability());
187  
  }
188  
  
189  
  L<ProbabilisticListListener<A>> listenersList() {
190  
    if (listeners == null) null;
191  
    synchronized { ret cloneList(listeners); }
192  
  }
193  
  
194  
  void fireElementAdded(A a, double probability) {
195  
    main forEach(listenersList(), l -> l.elementAdded(a, probability));
196  
  }
197  
  
198  
  synchronized void addListener(ProbabilisticListListener<A> l) {
199  
    listeners = addOrCreate(listeners, l);
200  
  }
201  
  
202  
  synchronized void removeListener(ProbabilisticListListener<A> l) {
203  
    listeners?.remove(l);
204  
  }
205  
  
206  
  void onElementAdded(IVF2<A, Double> f) {
207  
    if (f != null)
208  
      addListener(new ProbabilisticListAdapter<A> {
209  
        @Override
210  
        public void elementAdded(A a, double probability) {
211  
          f.get(a, probability);
212  
        }
213  
      });
214  
  }
215  
  
216  
}

Author comment

Began life as a copy of #1028471

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1031504
Snippet name: ProbabilisticList - list ordered by probability [OK!]
Eternal ID of this version: #1031504/56
Text MD5: e80072181788c6849cd110b70f422091
Transpilation MD5: 4ec8bbcefbe8fbbebb8d855dc21e23d1
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-09-02 20:28:57
Source code size: 6028 bytes / 216 lines
Pitched / IR pitched: No / No
Views / Downloads: 300 / 742
Version history: 55 change(s)
Referenced in: [show references]