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