4 // Copyright (C) 2004 Novell, Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 using System
.Collections
;
30 namespace Beagle
.Util
{
32 public class TopScores
{
34 private bool Debug
= false;
50 bool at_capacity
= false;
56 public TopScores (int count
)
59 this.nodes
= new Node
[count
];
60 for (int i
= 0; i
< count
; ++i
)
61 this.nodes
[i
].Clear ();
68 public long MinimumScore
{
76 score
= nodes
[i
].Score
;
83 public bool WillAccept (long score
)
85 return (! at_capacity
) || score
> cutoff_score
;
88 public void Add (long score
, object obj
)
90 if (at_capacity
&& score
<= cutoff_score
) {
92 Console
.WriteLine ("Skipping {0} ({1}), since threshold is {2}",
93 obj
, score
, cutoff_score
);
97 int node
, next_node
, prev_node
;
99 // If this is the first thing we are adding,
100 // make it the root node.
101 if (root_node
== -1) {
103 Console
.WriteLine ("Added {0} ({1}) as root node {2}", obj
, score
, free_node
);
104 root_node
= free_node
;
105 nodes
[free_node
].Score
= score
;
106 nodes
[free_node
].Obj
= obj
;
111 // If we are at capacity, find the leftmost node
117 // Find the leftmost node
119 next_node
= nodes
[node
].LtEq
;
126 // Detatch the node, and store its index
127 // in free_node so we can re-use it immediately.
128 if (prev_node
!= -1) {
129 // Detatching a non-root node
131 Console
.WriteLine ("Detatching {0} ({1}) from node {2}",
132 nodes
[node
].Obj
, nodes
[node
].Score
, node
);
133 nodes
[prev_node
].LtEq
= nodes
[node
].Gt
;
136 node
= prev_node
; // where to start looking for the new cut-off
138 // Detatching the root node
140 Console
.WriteLine ("Detatching {0} ({1}) from root node {2}",
141 nodes
[root_node
].Obj
, nodes
[root_node
].Score
, root_node
);
142 free_node
= root_node
;
143 root_node
= nodes
[root_node
].Gt
;
145 node
= root_node
; // where to start looking for the new cut-off
148 // Find the new cut-off
150 cutoff_score
= nodes
[node
].Score
;
151 node
= nodes
[node
].LtEq
;
154 nodes
[free_node
].Clear ();
157 Console
.WriteLine ("New cutoff is {0}", cutoff_score
);
161 // Find where we want to attach this node
162 bool is_lteq
= false;
164 next_node
= root_node
;
165 while (next_node
!= -1) {
167 if (score
<= nodes
[node
].Score
) {
168 next_node
= nodes
[node
].LtEq
;
171 next_node
= nodes
[node
].Gt
;
176 nodes
[free_node
].Score
= score
;
177 nodes
[free_node
].Obj
= obj
;
179 Console
.WriteLine ("Added {0} ({1}) as node {2}, under and {3} of {4}",
180 obj
, score
, free_node
, is_lteq
? "left" : "right", node
);
182 if (at_capacity
&& score
< cutoff_score
) {
183 cutoff_score
= score
;
185 Console
.WriteLine ("New cutoff is {0}", cutoff_score
);
190 nodes
[node
].LtEq
= free_node
;
192 nodes
[node
].Gt
= free_node
;
196 if (free_node
>= count
) {
197 cutoff_score
= MinimumScore
;
200 Console
.WriteLine ("Hit capacity: set cutoff to {0}", cutoff_score
);
206 private int ComputeMaxDepth (int i
)
210 int a
= 1 + ComputeMaxDepth (nodes
[i
].LtEq
);
211 int b
= 1 + ComputeMaxDepth (nodes
[i
].Gt
);
212 return Math
.Max (a
, b
);
215 public int MaxDepth
{
216 get { return ComputeMaxDepth (root_node); }
219 private void BuildArray (ArrayList array
, int i
)
222 BuildArray (array
, nodes
[i
].Gt
);
223 array
.Add (nodes
[i
].Obj
);
224 BuildArray (array
, nodes
[i
].LtEq
);
228 // Returns objects sorted from high to low scores
229 public ICollection TopScoringObjects
{
231 ArrayList array
= new ArrayList ();
232 BuildArray (array
, root_node
);
241 Random rng
= new Random ();
243 for (int j
= 0; j
< 1000; ++j
) {
245 Console
.WriteLine ("Trial #{0}", trial
);
248 top
= new TopScores (6 + rng
.Next (100));
250 ArrayList all
= new ArrayList ();
252 int N
= 100 + rng
.Next (100);
253 for (i
= 0; i
< N
; ++i
) {
254 int n
= rng
.Next (200);
261 foreach (object obj
in top
.TopScoringObjects
) {
262 if (! obj
.Equals (all
[i
])) {
263 Console
.WriteLine ("Mismatch!");
265 foreach (object x
in top
.TopScoringObjects
) {
266 Console
.WriteLine ("{0} {1} {2}",
268 x
.Equals (all
[i
]) ? "" : "***");