001    package org.maltparser.parser.history.kbest;
002    
003    import java.util.ArrayList;
004    
005    import org.maltparser.core.exception.MaltChainedException;
006    import org.maltparser.parser.history.action.SingleDecision;
007    /**
008    *
009    * @author Johan Hall
010    **/
011    public class KBestList {
012            protected final ArrayList<Candidate> kBestList;
013            protected int k = -1;
014            protected int topCandidateIndex;
015            protected int addCandidateIndex;
016            protected SingleDecision decision;
017            
018            /**
019             * Creates a unrestricted k-best list
020             * 
021             * @param decision a reference to the single decision that uses the k-best list
022             */
023            public KBestList(SingleDecision decision) {
024                    this(-1, decision);
025            }
026    
027            /**
028             * Creates a k-best list
029             * 
030             * @param k     the k-best list size
031             * @param decision      a reference to the single decision that uses the k-best list.
032             */
033            public KBestList(Integer k, SingleDecision decision) {
034                    setK(k.intValue());
035                    this.decision = decision;
036                    if (this.k > 0) {
037                            kBestList = new ArrayList<Candidate>(this.k);
038                            initKBestList();
039                    } else {
040                            kBestList = new ArrayList<Candidate>();
041                    }
042                    
043            }
044            
045            protected void initKBestList() {
046                    for (int i=0; i < this.k; i++) {
047                            kBestList.add(new Candidate());
048                    }
049            }
050            
051            /**
052             * Resets the k-best list
053             */
054            public void reset() {
055                    this.topCandidateIndex = 0;
056                    this.addCandidateIndex = 0;
057            }
058            
059            /**
060             * Adds a candidate to the k-best list
061             * 
062             * @param actionCode the integer representation  of candidate action
063             * @throws MaltChainedException
064             */
065            public void add(int actionCode) throws MaltChainedException {
066                    if (k != -1 && addCandidateIndex >= k) { return; }
067                    if (addCandidateIndex >= kBestList.size()) { kBestList.add(new Candidate()); }
068                    kBestList.get(addCandidateIndex).setActionCode(actionCode);
069                    if (addCandidateIndex == 0) {
070    //                      if (decision instanceof SingleDecision) {
071    //                              ((SingleDecision)decision).addDecision(actionCode);
072    //                      }
073                            decision.addDecision(actionCode);
074                            topCandidateIndex++;
075                    }
076                    addCandidateIndex++;
077            }
078            
079            public void addList(int[] predictionList) throws MaltChainedException {
080                    int n = (k != -1 && k <= predictionList.length-1)?k:predictionList.length - 1;
081                    for (int i=0; i<n; i++) {
082                            add(predictionList[i]);
083                    }       
084            }
085            
086            /**
087             * Adds a candidate to the k-best list
088             * 
089             * @param symbol the string representation of candidate action
090             * @throws MaltChainedException
091             */
092            public void add(String symbol) throws MaltChainedException {
093    //              if (decision instanceof SingleDecision) {
094    //                      this.add(((SingleDecision)decision).getDecisionCode(symbol));
095    //              }
096                    this.add(decision.getDecisionCode(symbol));
097            }
098            
099    
100            /**
101             * Updates the corresponding single decision with the next value in the k-best list.
102             * 
103             * @return true if decision has been updated, otherwise false
104             * @throws MaltChainedException
105             */
106            public boolean updateActionWithNextKBest() throws MaltChainedException {
107                    if (addCandidateIndex != 0 && topCandidateIndex < addCandidateIndex && topCandidateIndex < kBestList.size()) {
108                            int actionCode = kBestList.get(topCandidateIndex).getActionCode();
109                            if (decision instanceof SingleDecision) {
110                                    ((SingleDecision)decision).addDecision(actionCode);
111                            }
112                            topCandidateIndex++;
113                            return true;
114                    } 
115                    return false;
116            }
117            
118            public int peekNextKBest() {
119                    if (addCandidateIndex != 0 && topCandidateIndex < addCandidateIndex && topCandidateIndex < kBestList.size()) {
120                            return kBestList.get(topCandidateIndex).getActionCode();
121                    }
122                    return -1;
123            }
124            
125            /**
126             * Returns the current size of the k-best list
127             * 
128             * @return the current size of the k-best list
129             */
130            public int getCurrentSize() {
131                    return addCandidateIndex;
132                    //return kBestList.size();
133            }
134            
135            /**
136             * Returns the maximum number of candidates in the k-best list.
137             * 
138             * @return the maximum number of candidates in the k-best list
139             */
140            public int getK() {
141                    return k;
142            }
143            /**
144             * Sets the maximum number of candidates in the k-best list
145             * 
146             * @param k the maximum number of candidates 
147             */
148            protected void setK(int k) {
149                    if (k == 0) {
150                            this.k = 1; // the k-best list must contain at least one candidate
151                    } if (k < 0) {
152                            this.k = -1; // this means that the k-best list is unrestricted.
153                    } else {
154                            this.k = k;
155                    }
156            }
157            
158            protected int getTopCandidateIndex() {
159                    return topCandidateIndex;
160            }
161    
162            protected int getAddCandidateIndex() {
163                    return addCandidateIndex;
164            }
165    
166            /**
167             * Returns a single decision object
168             * 
169             * @return a single decision object
170             */
171            public SingleDecision getDecision() {
172                    return decision;
173            }       
174            
175            public int getKBestListSize() {
176                    return kBestList.size();
177            }
178            
179            public ScoredCandidate getCandidate(int i) {
180                    if (i >= kBestList.size()) {
181                            return null;
182                    }
183                    return (ScoredCandidate)kBestList.get(i);
184            }
185            
186            /* (non-Javadoc)
187             * @see java.lang.Object#toString()
188             */
189            public String toString() {
190                    final StringBuilder sb = new StringBuilder();
191                    sb.append("[ ");
192                    for (int i = 0; i < addCandidateIndex; i++) {
193                            sb.append(kBestList.get(i));
194                            sb.append(' ');
195                    }
196                    sb.append("] ");
197                    return sb.toString();
198            }
199    }