Index: src/test/org/apache/lucene/index/TestOmitTf.java =================================================================== --- src/test/org/apache/lucene/index/TestOmitTf.java (revision 0) +++ src/test/org/apache/lucene/index/TestOmitTf.java (revision 0) @@ -0,0 +1,363 @@ +package org.apache.lucene.index; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.util.Collection; + +import org.apache.lucene.util.LuceneTestCase; +import org.apache.lucene.util._TestUtil; +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.standard.StandardAnalyzer; +import org.apache.lucene.document.Document; +import org.apache.lucene.document.Field; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.HitCollector; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Searcher; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.BooleanClause.Occur; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.MockRAMDirectory; + + +public class TestOmitTf extends LuceneTestCase { + + public static class SimpleSimilarity extends Similarity { + public float lengthNorm(String field, int numTerms) { return 1.0f; } + public float queryNorm(float sumOfSquaredWeights) { return 1.0f; } + + public float tf(float freq) { return freq; } + + public float sloppyFreq(int distance) { return 2.0f; } + public float idf(Collection terms, Searcher searcher) { return 1.0f; } + public float idf(int docFreq, int numDocs) { return 1.0f; } + public float coord(int overlap, int maxOverlap) { return 1.0f; } + } + + + // Tests whether the DocumentWriter correctly enable the + // omitTf bit in the FieldInfo + public void testOmitTf() throws Exception { + Directory ram = new MockRAMDirectory(); + Analyzer analyzer = new StandardAnalyzer(); + IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); + Document d = new Document(); + + // this field will have Tf + Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED); + d.add(f1); + + // this field will NOT have Tf + Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED); + f2.setOmitTf(true); + d.add(f2); + + writer.addDocument(d); + writer.optimize(); + // now we add another document which has term freq for field f2 and not for f1 and verify if the SegmentMerger + // keep things constant + d = new Document(); + + // Reverese + f1.setOmitTf(true); + d.add(f1); + + f2.setOmitTf(false); + d.add(f2); + + writer.addDocument(d); + // force merge + writer.optimize(); + // flush + writer.close(); + _TestUtil.checkIndex(ram); + + // only one segment in the index, so we can cast to SegmentReader + SegmentReader reader = (SegmentReader) IndexReader.open(ram); + FieldInfos fi = reader.fieldInfos(); + assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f1").omitTf); + assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf); + + reader.close(); + ram.close(); + } + + // Tests whether merging of docs that have different + // omitTf for the same field works + public void testMixedMerge() throws Exception { + Directory ram = new MockRAMDirectory(); + Analyzer analyzer = new StandardAnalyzer(); + IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); + writer.setMaxBufferedDocs(3); + writer.setMergeFactor(2); + Document d = new Document(); + + // this field will have Tf + Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED); + d.add(f1); + + // this field will NOT have Tf + Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED); + f2.setOmitTf(true); + d.add(f2); + + for(int i=0;i<30;i++) + writer.addDocument(d); + + // now we add another document which has term freq for field f2 and not for f1 and verify if the SegmentMerger + // keep things constant + d = new Document(); + + // Reverese + f1.setOmitTf(true); + d.add(f1); + + f2.setOmitTf(false); + d.add(f2); + + for(int i=0;i<30;i++) + writer.addDocument(d); + + // force merge + writer.optimize(); + // flush + writer.close(); + + _TestUtil.checkIndex(ram); + + // only one segment in the index, so we can cast to SegmentReader + SegmentReader reader = (SegmentReader) IndexReader.open(ram); + FieldInfos fi = reader.fieldInfos(); + assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f1").omitTf); + assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf); + + reader.close(); + ram.close(); + } + + // Make sure first adding docs that do not omitTf for + // field X, then adding docs that do omitTf for that same + // field, + public void testMixedRAM() throws Exception { + Directory ram = new MockRAMDirectory(); + Analyzer analyzer = new StandardAnalyzer(); + IndexWriter writer = new IndexWriter(ram, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); + writer.setMaxBufferedDocs(10); + writer.setMergeFactor(2); + Document d = new Document(); + + // this field will have Tf + Field f1 = new Field("f1", "This field has term freqs", Field.Store.NO, Field.Index.TOKENIZED); + d.add(f1); + + // this field will NOT have Tf + Field f2 = new Field("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.TOKENIZED); + d.add(f2); + + for(int i=0;i<5;i++) + writer.addDocument(d); + + f2.setOmitTf(true); + + for(int i=0;i<20;i++) + writer.addDocument(d); + + // force merge + writer.optimize(); + + // flush + writer.close(); + + _TestUtil.checkIndex(ram); + + // only one segment in the index, so we can cast to SegmentReader + SegmentReader reader = (SegmentReader) IndexReader.open(ram); + FieldInfos fi = reader.fieldInfos(); + assertTrue("OmitTf field bit should not be set.", !fi.fieldInfo("f1").omitTf); + assertTrue("OmitTf field bit should be set.", fi.fieldInfo("f2").omitTf); + + reader.close(); + ram.close(); + } + + private void assertNoPrx(Directory dir) throws Throwable { + final String[] files = dir.list(); + for(int i=0;i>> 1; - if ((code & 1) != 0) - termFreq = 1; - else - termFreq = freq.readVInt(); + if (field.omitTf) + docID += code; + else { + docID += code >>> 1; + if ((code & 1) != 0) + termFreq = 1; + else + termFreq = freq.readVInt(); + } + assert docID != p.lastDocID; + return true; } } Index: src/java/org/apache/lucene/index/TermsHash.java =================================================================== --- src/java/org/apache/lucene/index/TermsHash.java (revision 678362) +++ src/java/org/apache/lucene/index/TermsHash.java (working copy) @@ -42,7 +42,6 @@ final TermsHash nextTermsHash; final int bytesPerPosting; final int postingsFreeChunk; - final int streamCount; final DocumentsWriter docWriter; TermsHash primaryTermsHash; @@ -55,7 +54,6 @@ public TermsHash(final DocumentsWriter docWriter, boolean trackAllocations, final TermsHashConsumer consumer, final TermsHash nextTermsHash) { this.docWriter = docWriter; this.consumer = consumer; - this.streamCount = consumer.streamCount; this.nextTermsHash = nextTermsHash; this.trackAllocations = trackAllocations; Index: src/java/org/apache/lucene/index/SegmentTermPositions.java =================================================================== --- src/java/org/apache/lucene/index/SegmentTermPositions.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentTermPositions.java (working copy) @@ -60,6 +60,9 @@ } public final int nextPosition() throws IOException { + if (currentFieldOmitTf) + // This field does not store term freq, positions, payloads + return 0; // perform lazy skips if neccessary lazySkip(); proxCount--; @@ -116,6 +119,7 @@ } private void skipPositions(int n) throws IOException { + assert !currentFieldOmitTf; for (int f = n; f > 0; f--) { // skip unread positions readDeltaPosition(); skipPayload(); Index: src/java/org/apache/lucene/index/SegmentMerger.java =================================================================== --- src/java/org/apache/lucene/index/SegmentMerger.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentMerger.java (working copy) @@ -83,6 +83,10 @@ checkAbort = new CheckAbort(merge, directory); termIndexInterval = writer.getTermIndexInterval(); } + + boolean hasProx() { + return fieldInfos.hasProx(); + } /** * Add an IndexReader to the collection of readers that are to be merged @@ -164,6 +168,10 @@ // Basic files for (int i = 0; i < IndexFileNames.COMPOUND_EXTENSIONS.length; i++) { String ext = IndexFileNames.COMPOUND_EXTENSIONS[i]; + + if (ext.equals(IndexFileNames.PROX_EXTENSION) && !hasProx()) + continue; + if (mergeDocStores || (!ext.equals(IndexFileNames.FIELDS_EXTENSION) && !ext.equals(IndexFileNames.FIELDS_INDEX_EXTENSION))) files.add(segment + "." + ext); @@ -198,11 +206,11 @@ } private void addIndexed(IndexReader reader, FieldInfos fieldInfos, Collection names, boolean storeTermVectors, boolean storePositionWithTermVector, - boolean storeOffsetWithTermVector, boolean storePayloads) throws IOException { + boolean storeOffsetWithTermVector, boolean storePayloads, boolean omitTf) throws IOException { Iterator i = names.iterator(); while (i.hasNext()) { String field = (String)i.next(); - fieldInfos.add(field, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector, !reader.hasNorms(field), storePayloads); + fieldInfos.add(field, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector, !reader.hasNorms(field), storePayloads, omitTf); } } @@ -265,15 +273,16 @@ SegmentReader segmentReader = (SegmentReader) reader; for (int j = 0; j < segmentReader.getFieldInfos().size(); j++) { FieldInfo fi = segmentReader.getFieldInfos().fieldInfo(j); - fieldInfos.add(fi.name, fi.isIndexed, fi.storeTermVector, fi.storePositionWithTermVector, fi.storeOffsetWithTermVector, !reader.hasNorms(fi.name), fi.storePayloads); + fieldInfos.add(fi.name, fi.isIndexed, fi.storeTermVector, fi.storePositionWithTermVector, fi.storeOffsetWithTermVector, !reader.hasNorms(fi.name), fi.storePayloads, fi.omitTf); } } else { - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION_OFFSET), true, true, true, false); - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION), true, true, false, false); - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_OFFSET), true, false, true, false); - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR), true, false, false, false); - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.STORES_PAYLOADS), false, false, false, true); - addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.INDEXED), false, false, false, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION_OFFSET), true, true, true, false, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION), true, true, false, false, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_OFFSET), true, false, true, false, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.TERMVECTOR), true, false, false, false, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.OMIT_TF), false, false, false, false, true); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.STORES_PAYLOADS), false, false, false, true, false); + addIndexed(reader, fieldInfos, reader.getFieldNames(IndexReader.FieldOption.INDEXED), false, false, false, false, false); fieldInfos.add(reader.getFieldNames(IndexReader.FieldOption.UNINDEXED), false); } } @@ -477,7 +486,8 @@ private final void mergeTerms() throws CorruptIndexException, IOException { try { freqOutput = directory.createOutput(segment + ".frq"); - proxOutput = directory.createOutput(segment + ".prx"); + if (hasProx()) + proxOutput = directory.createOutput(segment + ".prx"); termInfosWriter = new TermInfosWriter(directory, segment, fieldInfos, termIndexInterval); @@ -561,11 +571,20 @@ */ private final int mergeTermInfo(SegmentMergeInfo[] smis, int n) throws CorruptIndexException, IOException { - long freqPointer = freqOutput.getFilePointer(); - long proxPointer = proxOutput.getFilePointer(); + final long freqPointer = freqOutput.getFilePointer(); + final long proxPointer; + if (proxOutput != null) + proxPointer = proxOutput.getFilePointer(); + else + proxPointer = 0; - int df = appendPostings(smis, n); // append posting data - + int df; + if (fieldInfos.fieldInfo(smis[0].term.field).omitTf) { // append posting data + df = appendPostingsNoTf(smis, n); + } else{ + df = appendPostings(smis, n); + } + long skipPointer = skipListWriter.writeSkip(freqOutput); if (df > 0) { @@ -672,6 +691,53 @@ return df; } + /** Process postings from multiple segments without tf, all positioned on the + * same term. Writes out merged entries only into freqOutput, proxOut is not written. + * + * @param smis array of segments + * @param n number of cells in the array actually occupied + * @return number of documents across all segments where this term was found + * @throws CorruptIndexException if the index is corrupt + * @throws IOException if there is a low-level IO error + */ + private final int appendPostingsNoTf(SegmentMergeInfo[] smis, int n) + throws CorruptIndexException, IOException { + int lastDoc = 0; + int df = 0; // number of docs w/ term + skipListWriter.resetSkip(); + int lastPayloadLength = -1; // ensures that we write the first length + for (int i = 0; i < n; i++) { + SegmentMergeInfo smi = smis[i]; + TermPositions postings = smi.getPositions(); + assert postings != null; + int base = smi.base; + int[] docMap = smi.getDocMap(); + postings.seek(smi.termEnum); + while (postings.next()) { + int doc = postings.doc(); + if (docMap != null) + doc = docMap[doc]; // map around deletions + doc += base; // convert to merged space + + if (doc < 0 || (df > 0 && doc <= lastDoc)) + throw new CorruptIndexException("docs out of order (" + doc + + " <= " + lastDoc + " )"); + + df++; + + if ((df % skipInterval) == 0) { + skipListWriter.setSkipData(lastDoc, false, lastPayloadLength); + skipListWriter.bufferSkip(df); + } + + int docCode = (doc - lastDoc); + lastDoc = doc; + freqOutput.writeVInt(docCode); // write doc & freq=1 + } + } + return df; + } + private void mergeNorms() throws IOException { byte[] normBuffer = null; IndexOutput output = null; Index: src/java/org/apache/lucene/index/TermsHashPerField.java =================================================================== --- src/java/org/apache/lucene/index/TermsHashPerField.java (revision 678362) +++ src/java/org/apache/lucene/index/TermsHashPerField.java (working copy) @@ -57,9 +57,9 @@ bytePool = perThread.bytePool; docState = perThread.docState; fieldState = docInverterPerField.fieldState; - streamCount = perThread.termsHash.streamCount; + this.consumer = perThread.consumer.addField(this, fieldInfo); + streamCount = consumer.getStreamCount(); numPostingInt = 2*streamCount; - this.consumer = perThread.consumer.addField(this, fieldInfo); this.fieldInfo = fieldInfo; if (nextPerThread != null) nextPerField = (TermsHashPerField) nextPerThread.addField(docInverterPerField, fieldInfo); @@ -488,6 +488,7 @@ } void writeVInt(int stream, int i) { + assert stream < streamCount; while ((i & ~0x7F) != 0) { writeByte(stream, (byte)((i & 0x7f) | 0x80)); i >>>= 7; Index: src/java/org/apache/lucene/index/SegmentInfo.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfo.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentInfo.java (working copy) @@ -77,6 +77,8 @@ private int delCount; // How many deleted docs in this segment, or -1 if not yet known // (if it's an older index) + private boolean hasProx; // True if this segment has any fields with omitTf==false + public SegmentInfo(String name, int docCount, Directory dir) { this.name = name; this.docCount = docCount; @@ -89,14 +91,15 @@ docStoreSegment = name; docStoreIsCompoundFile = false; delCount = 0; + hasProx = true; } public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile) { - this(name, docCount, dir, isCompoundFile, hasSingleNormFile, -1, null, false); + this(name, docCount, dir, isCompoundFile, hasSingleNormFile, -1, null, false, true); } public SegmentInfo(String name, int docCount, Directory dir, boolean isCompoundFile, boolean hasSingleNormFile, - int docStoreOffset, String docStoreSegment, boolean docStoreIsCompoundFile) { + int docStoreOffset, String docStoreSegment, boolean docStoreIsCompoundFile, boolean hasProx) { this(name, docCount, dir); this.isCompoundFile = (byte) (isCompoundFile ? YES : NO); this.hasSingleNormFile = hasSingleNormFile; @@ -104,6 +107,7 @@ this.docStoreOffset = docStoreOffset; this.docStoreSegment = docStoreSegment; this.docStoreIsCompoundFile = docStoreIsCompoundFile; + this.hasProx = hasProx; delCount = 0; assert docStoreOffset == -1 || docStoreSegment != null; } @@ -180,6 +184,10 @@ assert delCount <= docCount; } else delCount = -1; + if (format <= SegmentInfos.FORMAT_HAS_PROX) + hasProx = input.readByte() == 1; + else + hasProx = true; } else { delGen = CHECK_DIR; normGen = null; @@ -190,6 +198,7 @@ docStoreIsCompoundFile = false; docStoreSegment = null; delCount = -1; + hasProx = true; } } @@ -507,8 +516,18 @@ } output.writeByte(isCompoundFile); output.writeInt(delCount); + output.writeByte((byte) (hasProx ? 1:0)); } + void setHasProx(boolean hasProx) { + this.hasProx = hasProx; + clearFiles(); + } + + boolean getHasProx() { + return hasProx; + } + private void addIfExists(List files, String fileName) throws IOException { if (dir.fileExists(fileName)) files.add(fileName); Index: src/java/org/apache/lucene/index/FreqProxTermsWriter.java =================================================================== --- src/java/org/apache/lucene/index/FreqProxTermsWriter.java (revision 678362) +++ src/java/org/apache/lucene/index/FreqProxTermsWriter.java (working copy) @@ -31,10 +31,6 @@ final class FreqProxTermsWriter extends TermsHashConsumer { - FreqProxTermsWriter() { - streamCount = 2; - } - public TermsHashConsumerPerThread addThread(TermsHashPerThread perThread) { return new FreqProxTermsWriterPerThread(perThread); } @@ -102,8 +98,13 @@ state.docWriter.writer.getTermIndexInterval()); final IndexOutput freqOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.FREQ_EXTENSION)); - final IndexOutput proxOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.PROX_EXTENSION)); + final IndexOutput proxOut; + if (fieldInfos.hasProx()) + proxOut = state.directory.createOutput(state.segmentFileName(IndexFileNames.PROX_EXTENSION)); + else + proxOut = null; + final DefaultSkipListWriter skipListWriter = new DefaultSkipListWriter(termsOut.skipInterval, termsOut.maxSkipLevels, state.numDocsInRAM, freqOut, proxOut); @@ -135,6 +136,7 @@ int numPostings = perField.numPostings; perField.reset(); perField.shrinkHash(numPostings); + fields[i].reset(); } start = end; @@ -148,13 +150,15 @@ } freqOut.close(); - proxOut.close(); + if (proxOut != null) { + state.flushedFiles.add(state.segmentFileName(IndexFileNames.PROX_EXTENSION)); + proxOut.close(); + } termsOut.close(); // Record all files we have flushed state.flushedFiles.add(state.segmentFileName(IndexFileNames.FIELD_INFOS_EXTENSION)); state.flushedFiles.add(state.segmentFileName(IndexFileNames.FREQ_EXTENSION)); - state.flushedFiles.add(state.segmentFileName(IndexFileNames.PROX_EXTENSION)); state.flushedFiles.add(state.segmentFileName(IndexFileNames.TERMS_EXTENSION)); state.flushedFiles.add(state.segmentFileName(IndexFileNames.TERMS_INDEX_EXTENSION)); } @@ -205,8 +209,12 @@ } final int skipInterval = termsOut.skipInterval; - final boolean currentFieldStorePayloads = fields[0].fieldInfo.storePayloads; + final boolean currentFieldOmitTf = fields[0].fieldInfo.omitTf; + // If current field omits tf then it cannot store + // payloads. We silently drop the payloads in this case: + final boolean currentFieldStorePayloads = currentFieldOmitTf ? false : fields[0].fieldInfo.storePayloads; + FreqProxFieldMergeState[] termStates = new FreqProxFieldMergeState[numFields]; while(numFields > 0) { @@ -235,8 +243,12 @@ final char[] text = termStates[0].text; final int start = termStates[0].textOffset; - long freqPointer = freqOut.getFilePointer(); - long proxPointer = proxOut.getFilePointer(); + final long freqPointer = freqOut.getFilePointer(); + final long proxPointer; + if (proxOut != null) + proxPointer = proxOut.getFilePointer(); + else + proxPointer = 0; skipListWriter.resetSkip(); @@ -261,45 +273,53 @@ assert doc < flushState.numDocsInRAM; assert doc > lastDoc || df == 1; - final int newDocCode = (doc-lastDoc)<<1; - - lastDoc = doc; - final ByteSliceReader prox = minState.prox; // Carefully copy over the prox + payload info, // changing the format to match Lucene's segment // format. - for(int j=0;j 0) - copyBytes(prox, proxOut, payloadLength); - } else { - assert 0 == (code & 1); - proxOut.writeVInt(code>>1); + if (!currentFieldOmitTf) { + // omitTf == false so we do write positions & payload + assert proxOut != null; + for(int j=0;j 0) + copyBytes(prox, proxOut, payloadLength); + } else { + assert 0 == (code & 1); + proxOut.writeVInt(code>>1); + } + } //End for + + final int newDocCode = (doc-lastDoc)<<1; + + if (1 == termDocFreq) { + freqOut.writeVInt(newDocCode|1); + } else { + freqOut.writeVInt(newDocCode); + freqOut.writeVInt(termDocFreq); } - } - - if (1 == termDocFreq) { - freqOut.writeVInt(newDocCode|1); } else { - freqOut.writeVInt(newDocCode); - freqOut.writeVInt(termDocFreq); + // omitTf==true: we store only the docs, without + // term freq, positions, payloads + freqOut.writeVInt(doc-lastDoc); } + lastDoc = doc; + if (!minState.nextDoc()) { // Remove from termStates Index: src/java/org/apache/lucene/index/SegmentReader.java =================================================================== --- src/java/org/apache/lucene/index/SegmentReader.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentReader.java (working copy) @@ -298,6 +298,12 @@ fieldInfos = new FieldInfos(cfsDir, segment + ".fnm"); + boolean anyProx = false; + final int numFields = fieldInfos.size(); + for(int i=0;!anyProx && i 0; + assert omitTf || p.docFreq > 0; - if (docState.docID != p.lastDocID) { - // Term not yet seen in the current doc but previously - // seen in other doc(s) since the last flush - - // Now that we know doc freq for previous doc, - // write it & lastDocCode - if (1 == p.docFreq) - termsHashPerField.writeVInt(0, p.lastDocCode|1); - else { + if (omitTf) { + if (docState.docID != p.lastDocID) { + assert docState.docID > p.lastDocID; termsHashPerField.writeVInt(0, p.lastDocCode); - termsHashPerField.writeVInt(0, p.docFreq); + p.lastDocCode = docState.docID - p.lastDocID; + p.lastDocID = docState.docID; } - p.docFreq = 1; - p.lastDocCode = (docState.docID - p.lastDocID) << 1; - p.lastDocID = docState.docID; - writeProx(t, p, fieldState.position); } else { - p.docFreq++; - writeProx(t, p, fieldState.position-p.lastPosition); + if (docState.docID != p.lastDocID) { + assert docState.docID > p.lastDocID; + // Term not yet seen in the current doc but previously + // seen in other doc(s) since the last flush + + // Now that we know doc freq for previous doc, + // write it & lastDocCode + if (1 == p.docFreq) + termsHashPerField.writeVInt(0, p.lastDocCode|1); + else { + termsHashPerField.writeVInt(0, p.lastDocCode); + termsHashPerField.writeVInt(0, p.docFreq); + } + p.docFreq = 1; + p.lastDocCode = (docState.docID - p.lastDocID) << 1; + p.lastDocID = docState.docID; + writeProx(t, p, fieldState.position); + } else { + p.docFreq++; + writeProx(t, p, fieldState.position-p.lastPosition); + } } } Index: src/java/org/apache/lucene/index/FieldInfo.java =================================================================== --- src/java/org/apache/lucene/index/FieldInfo.java (revision 678362) +++ src/java/org/apache/lucene/index/FieldInfo.java (working copy) @@ -27,13 +27,14 @@ boolean storeOffsetWithTermVector; boolean storePositionWithTermVector; - boolean omitNorms; // omit norms associated with indexed fields + boolean omitNorms; // omit norms associated with indexed fields + boolean omitTf; // omit tf boolean storePayloads; // whether this field stores payloads together with term positions FieldInfo(String na, boolean tk, int nu, boolean storeTermVector, boolean storePositionWithTermVector, boolean storeOffsetWithTermVector, - boolean omitNorms, boolean storePayloads) { + boolean omitNorms, boolean storePayloads, boolean omitTf) { name = na; isIndexed = tk; number = nu; @@ -42,15 +43,16 @@ this.storePositionWithTermVector = storePositionWithTermVector; this.omitNorms = omitNorms; this.storePayloads = storePayloads; + this.omitTf = omitTf; } public Object clone() { return new FieldInfo(name, isIndexed, number, storeTermVector, storePositionWithTermVector, - storeOffsetWithTermVector, omitNorms, storePayloads); + storeOffsetWithTermVector, omitNorms, storePayloads, omitTf); } void update(boolean isIndexed, boolean storeTermVector, boolean storePositionWithTermVector, - boolean storeOffsetWithTermVector, boolean omitNorms, boolean storePayloads) { + boolean storeOffsetWithTermVector, boolean omitNorms, boolean storePayloads, boolean omitTf) { if (this.isIndexed != isIndexed) { this.isIndexed = true; // once indexed, always index } @@ -66,6 +68,9 @@ if (this.omitNorms != omitNorms) { this.omitNorms = false; // once norms are stored, always store } + if (this.omitTf != omitTf) { + this.omitTf = true; // if one require omitTf at least once, it remains off for life + } if (this.storePayloads != storePayloads) { this.storePayloads = true; } @@ -87,6 +92,9 @@ if (omitNorms != other.omitNorms) { omitNorms = false; // once norms are stored, always store } + if (this.omitTf != omitTf) { + this.omitTf = true; // if one require omitTf at least once, it remains off for life + } if (storePayloads != other.storePayloads) { storePayloads = true; } Index: src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java =================================================================== --- src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java (revision 678362) +++ src/java/org/apache/lucene/index/DocFieldProcessorPerThread.java (working copy) @@ -183,7 +183,7 @@ // easily add it FieldInfo fi = fieldInfos.add(fieldName, field.isIndexed(), field.isTermVectorStored(), field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(), - field.getOmitNorms(), false); + field.getOmitNorms(), false, field.getOmitTf()); fp = new DocFieldProcessorPerField(this, fi); fp.next = fieldHash[hashPos]; @@ -195,7 +195,7 @@ } else fp.fieldInfo.update(field.isIndexed(), field.isTermVectorStored(), field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(), - field.getOmitNorms(), false); + field.getOmitNorms(), false, field.getOmitTf()); if (thisFieldGen != fp.lastGen) { Index: src/java/org/apache/lucene/index/TermsHashConsumer.java =================================================================== --- src/java/org/apache/lucene/index/TermsHashConsumer.java (revision 678362) +++ src/java/org/apache/lucene/index/TermsHashConsumer.java (working copy) @@ -28,8 +28,6 @@ abstract void abort(); abstract void closeDocStore(DocumentsWriter.FlushState state) throws IOException; - int streamCount; - FieldInfos fieldInfos; void setFieldInfos(FieldInfos fieldInfos) { Index: src/java/org/apache/lucene/index/TermVectorsTermsWriter.java =================================================================== --- src/java/org/apache/lucene/index/TermVectorsTermsWriter.java (revision 678362) +++ src/java/org/apache/lucene/index/TermVectorsTermsWriter.java (working copy) @@ -39,7 +39,6 @@ public TermVectorsTermsWriter(DocumentsWriter docWriter) { this.docWriter = docWriter; - streamCount = 2; } public TermsHashConsumerPerThread addThread(TermsHashPerThread termsHashPerThread) { Index: src/java/org/apache/lucene/index/TermsHashConsumerPerField.java =================================================================== --- src/java/org/apache/lucene/index/TermsHashConsumerPerField.java (revision 678362) +++ src/java/org/apache/lucene/index/TermsHashConsumerPerField.java (working copy) @@ -32,4 +32,5 @@ abstract void skippingLongTerm(Token t) throws IOException; abstract void newTerm(Token t, RawPostingList p) throws IOException; abstract void addTerm(Token t, RawPostingList p) throws IOException; + abstract int getStreamCount(); } Index: src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- src/java/org/apache/lucene/index/IndexReader.java (revision 678362) +++ src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -75,6 +75,8 @@ public static final FieldOption INDEXED = new FieldOption ("INDEXED"); /** All fields that store payloads */ public static final FieldOption STORES_PAYLOADS = new FieldOption ("STORES_PAYLOADS"); + /** All fields that omit tf */ + public static final FieldOption OMIT_TF = new FieldOption ("OMIT_TF"); /** All fields which are not indexed */ public static final FieldOption UNINDEXED = new FieldOption ("UNINDEXED"); /** All fields which are indexed with termvectors enabled */ Index: src/java/org/apache/lucene/index/DocumentsWriter.java =================================================================== --- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 678362) +++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy) @@ -132,6 +132,8 @@ boolean bufferIsFull; // True when it's time to write segment private boolean aborting; // True if an abort is pending + private DocFieldProcessor docFieldProcessor; + PrintStream infoStream; int maxFieldLength = IndexWriter.DEFAULT_MAX_FIELD_LENGTH; Similarity similarity; @@ -261,9 +263,15 @@ final DocInverter docInverter = new DocInverter(termsHash, normsWriter); final StoredFieldsWriter fieldsWriter = new StoredFieldsWriter(this); final DocFieldConsumers docFieldConsumers = new DocFieldConsumers(docInverter, fieldsWriter); - consumer = new DocFieldProcessor(this, docFieldConsumers); + consumer = docFieldProcessor = new DocFieldProcessor(this, docFieldConsumers); } + /** Returns true if any of the fields in the current + * buffered docs have omitTf==false */ + boolean hasProx() { + return docFieldProcessor.fieldInfos.hasProx(); + } + /** If non-null, various details of indexing are printed * here. */ synchronized void setInfoStream(PrintStream infoStream) { Index: src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java =================================================================== --- src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java (revision 678362) +++ src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java (working copy) @@ -47,6 +47,10 @@ fieldState = termsHashPerField.fieldState; } + int getStreamCount() { + return 2; + } + boolean start(Fieldable[] fields, int count) { doVectors = false; doVectorPositions = false; Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -65,8 +65,13 @@ * This way IndexWriter can efficiently report numDocs(). */ public static final int FORMAT_DEL_COUNT = -6; + /** This format adds the boolean hasProx to record if any + * fields in the segment store prox information (ie, have + * omitTf==false) */ + public static final int FORMAT_HAS_PROX = -7; + /* This must always point to the most recent file format. */ - static final int CURRENT_FORMAT = FORMAT_DEL_COUNT; + static final int CURRENT_FORMAT = FORMAT_HAS_PROX; public int counter = 0; // used to name new segments /** Index: src/java/org/apache/lucene/index/SegmentTermDocs.java =================================================================== --- src/java/org/apache/lucene/index/SegmentTermDocs.java (revision 678362) +++ src/java/org/apache/lucene/index/SegmentTermDocs.java (working copy) @@ -41,7 +41,8 @@ private boolean haveSkipped; protected boolean currentFieldStoresPayloads; - + protected boolean currentFieldOmitTf; + protected SegmentTermDocs(SegmentReader parent) { this.parent = parent; this.freqStream = (IndexInput) parent.freqStream.clone(); @@ -75,6 +76,7 @@ void seek(TermInfo ti, Term term) throws IOException { count = 0; FieldInfo fi = parent.fieldInfos.fieldInfo(term.field); + currentFieldOmitTf = (fi != null) ? fi.omitTf : false; currentFieldStoresPayloads = (fi != null) ? fi.storePayloads : false; if (ti == null) { df = 0; @@ -105,14 +107,19 @@ while (true) { if (count == df) return false; - - int docCode = freqStream.readVInt(); - doc += docCode >>> 1; // shift off low bit - if ((docCode & 1) != 0) // if low bit is set - freq = 1; // freq is one - else - freq = freqStream.readVInt(); // else read freq - + final int docCode = freqStream.readVInt(); + + if (currentFieldOmitTf) { + doc += docCode; + freq = 1; + } else { + doc += docCode >>> 1; // shift off low bit + if ((docCode & 1) != 0) // if low bit is set + freq = 1; // freq is one + else + freq = freqStream.readVInt(); // else read freq + } + count++; if (deletedDocs == null || !deletedDocs.get(doc)) @@ -126,27 +133,49 @@ public int read(final int[] docs, final int[] freqs) throws IOException { final int length = docs.length; + if (currentFieldOmitTf) { + return readNoTf(docs, freqs, length); + } else { + int i = 0; + while (i < length && count < df) { + // manually inlined call to next() for speed + final int docCode = freqStream.readVInt(); + doc += docCode >>> 1; // shift off low bit + if ((docCode & 1) != 0) // if low bit is set + freq = 1; // freq is one + else + freq = freqStream.readVInt(); // else read freq + count++; + + if (deletedDocs == null || !deletedDocs.get(doc)) { + docs[i] = doc; + freqs[i] = freq; + ++i; + } + } + return i; + } + } + + private final int readNoTf(final int[] docs, final int[] freqs, final int length) throws IOException { int i = 0; while (i < length && count < df) { - // manually inlined call to next() for speed - final int docCode = freqStream.readVInt(); - doc += docCode >>> 1; // shift off low bit - if ((docCode & 1) != 0) // if low bit is set - freq = 1; // freq is one - else - freq = freqStream.readVInt(); // else read freq + doc += freqStream.readVInt(); count++; if (deletedDocs == null || !deletedDocs.get(doc)) { docs[i] = doc; - freqs[i] = freq; + // Hardware freq to 1 when term freqs were not + // stored in the index + freqs[i] = 1; ++i; } } return i; } - + + /** Overridden by SegmentTermPositions to skip in prox stream. */ protected void skipProx(long proxPointer, int payloadLength) throws IOException {} Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 678362) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -3054,7 +3054,7 @@ synchronized(this) { segmentInfos.setSize(0); // pop old infos & add new info = new SegmentInfo(mergedName, docCount, directory, false, true, - -1, null, false); + -1, null, false, merger.hasProx()); segmentInfos.addElement(info); } @@ -3362,7 +3362,8 @@ flushedDocCount, directory, false, true, docStoreOffset, docStoreSegment, - docStoreIsCompoundFile); + docStoreIsCompoundFile, + docWriter.hasProx()); } docWriter.pushDeletes(); @@ -3600,6 +3601,8 @@ } } + merge.info.setHasProx(merger.hasProx()); + segmentInfos.subList(start, start + merge.segments.size()).clear(); segmentInfos.add(start, merge.info); @@ -3890,7 +3893,8 @@ directory, false, true, docStoreOffset, docStoreSegment, - docStoreIsCompoundFile); + docStoreIsCompoundFile, + false); // Also enroll the merged segment into mergingSegments; // this prevents it from getting selected for a merge Index: src/java/org/apache/lucene/index/DefaultSkipListWriter.java =================================================================== --- src/java/org/apache/lucene/index/DefaultSkipListWriter.java (revision 678362) +++ src/java/org/apache/lucene/index/DefaultSkipListWriter.java (working copy) @@ -62,7 +62,8 @@ this.curStorePayloads = storePayloads; this.curPayloadLength = payloadLength; this.curFreqPointer = freqOutput.getFilePointer(); - this.curProxPointer = proxOutput.getFilePointer(); + if (proxOutput != null) + this.curProxPointer = proxOutput.getFilePointer(); } protected void resetSkip() { @@ -70,7 +71,8 @@ Arrays.fill(lastSkipDoc, 0); Arrays.fill(lastSkipPayloadLength, -1); // we don't have to write the first length in the skip list Arrays.fill(lastSkipFreqPointer, freqOutput.getFilePointer()); - Arrays.fill(lastSkipProxPointer, proxOutput.getFilePointer()); + if (proxOutput != null) + Arrays.fill(lastSkipProxPointer, proxOutput.getFilePointer()); } protected void writeSkipData(int level, IndexOutput skipBuffer) throws IOException { Index: src/java/org/apache/lucene/index/CheckIndex.java =================================================================== --- src/java/org/apache/lucene/index/CheckIndex.java (revision 678362) +++ src/java/org/apache/lucene/index/CheckIndex.java (working copy) @@ -114,13 +114,12 @@ else if (format == SegmentInfos.FORMAT_SHARED_DOC_STORE) sFormat = "FORMAT_SHARED_DOC_STORE [Lucene 2.3]"; else { - // LUCENE-1255: All versions before 2.3.2/2.4 were - // able to create position=-1 when the very first - // Token has positionIncrement 0 if (format == SegmentInfos.FORMAT_CHECKSUM) sFormat = "FORMAT_CHECKSUM [Lucene 2.4]"; else if (format == SegmentInfos.FORMAT_DEL_COUNT) - sFormat = "FORMAT_DEL_COUNT [Lucene 2.4]"; + sFormat = "FORMAT_DEL_COUNT [Lucene 2.4]"; + else if (format == SegmentInfos.FORMAT_HAS_PROX) + sFormat = "FORMAT_HAS_PROX [Lucene 2.4]"; else if (format < SegmentInfos.CURRENT_FORMAT) { sFormat = "int=" + format + " [newer version of Lucene than this tool]"; skip = true; @@ -161,6 +160,7 @@ try { out.println(" compound=" + info.getUseCompoundFile()); + out.println(" hasProx=" + info.getHasProx()); out.println(" numFiles=" + info.files().size()); out.println(" size (MB)=" + nf.format(info.sizeInBytes()/(1024.*1024.))); final int docStoreOffset = info.getDocStoreOffset(); @@ -224,7 +224,7 @@ final int doc = termPositions.doc(); final int freq = termPositions.freq(); if (doc <= lastDoc) - throw new RuntimeException("term " + term + ": doc " + doc + " < lastDoc " + lastDoc); + throw new RuntimeException("term " + term + ": doc " + doc + " <= lastDoc " + lastDoc); lastDoc = doc; if (freq <= 0) throw new RuntimeException("term " + term + ": doc " + doc + ": freq " + freq + " is out of bounds"); Index: src/java/org/apache/lucene/document/AbstractField.java =================================================================== --- src/java/org/apache/lucene/document/AbstractField.java (revision 678362) +++ src/java/org/apache/lucene/document/AbstractField.java (working copy) @@ -33,6 +33,7 @@ protected boolean isBinary = false; protected boolean isCompressed = false; protected boolean lazy = false; + protected boolean omitTf = false; protected float boost = 1.0f; // the one and only data object for all different kind of field values protected Object fieldsData = null; @@ -203,6 +204,9 @@ /** True if norms are omitted for this indexed field */ public boolean getOmitNorms() { return omitNorms; } + /** True if tf is omitted for this indexed field */ + public boolean getOmitTf() { return omitTf; } + /** Expert: * * If set, omit normalization factors associated with this indexed field. @@ -210,6 +214,12 @@ */ public void setOmitNorms(boolean omitNorms) { this.omitNorms=omitNorms; } + /** Expert: + * + * If set, omit tf from postings of this indexed field. + */ + public void setOmitTf(boolean omitTf) { this.omitTf=omitTf; } + public boolean isLazy() { return lazy; } @@ -257,6 +267,9 @@ if (omitNorms) { result.append(",omitNorms"); } + if (omitTf) { + result.append(",omitTf"); + } if (lazy){ result.append(",lazy"); } Index: src/java/org/apache/lucene/document/Fieldable.java =================================================================== --- src/java/org/apache/lucene/document/Fieldable.java (revision 678362) +++ src/java/org/apache/lucene/document/Fieldable.java (working copy) @@ -133,6 +133,15 @@ */ void setOmitNorms(boolean omitNorms); + /** Expert: + * + * If set, omit term freq, positions and payloads from postings for this field. + */ + void setOmitTf(boolean omitTf); + + /** True if tf is omitted for this indexed field */ + boolean getOmitTf(); + /** * Indicates whether a Field is Lazy or not. The semantics of Lazy loading are such that if a Field is lazily loaded, retrieving * it's values via {@link #stringValue()} or {@link #binaryValue()} is only valid as long as the {@link org.apache.lucene.index.IndexReader} that Index: src/site/src/documentation/content/xdocs/fileformats.xml =================================================================== --- src/site/src/documentation/content/xdocs/fileformats.xml (revision 678362) +++ src/site/src/documentation/content/xdocs/fileformats.xml (working copy) @@ -246,14 +246,16 @@

Term Frequency data. For each term in the dictionary, the numbers of all the documents that contain that term, and the frequency of the term in - that document. + that document if omitTf is false.

  • Term Proximity data. For each term in the dictionary, the positions that the term - occurs in each document. + occurs in each document. Note that this will + not exist if all fields in all documents set + omitTf to true.

  • @@ -826,11 +828,12 @@ 2.4 and above: Segments --> Format, Version, NameCounter, SegCount, <SegName, SegSize, DelGen, DocStoreOffset, [DocStoreSegment, DocStoreIsCompoundFile], HasSingleNormFile, NumField, NormGenNumField, - IsCompoundFile>SegCount, Checksum + IsCompoundFile, DeletionCount, HasProx>SegCount, Checksum

    - Format, NameCounter, SegCount, SegSize, NumField, DocStoreOffset --> Int32 + Format, NameCounter, SegCount, SegSize, NumField, + DocStoreOffset, DeletionCount --> Int32

    @@ -842,7 +845,8 @@

    - IsCompoundFile, HasSingleNormFile, DocStoreIsCompoundFile --> Int8 + IsCompoundFile, HasSingleNormFile, + DocStoreIsCompoundFile, HasProx --> Int8

    @@ -936,8 +940,17 @@ This is used to verify integrity of the file on opening the index.

    - +

    + DeletionCount records the number of deleted + documents in this segment. +

    + +

    + HasProx is 1 if any fields in this segment have + omitTf set to false; else, it's 0. +

    +
    Lock File @@ -1264,7 +1277,9 @@ determines the position of this term's TermPositions within the .prx file. In particular, it is the difference between the position of this term's data in that file and the position of the previous - term's data (or zero, for the first term in the file. + term's data (or zero, for the first term in the file. For fields + with omitTf true, this will be 0 since + prox information is not stored.

    SkipDelta determines the position of this term's SkipData within the .frq file. In @@ -1338,7 +1353,7 @@

    The .frq file contains the lists of documents which contain each term, along with the frequency of the term in that - document. + document (if omitTf is false).

    FreqFile (.frq) --> <TermFreqs, SkipData> @@ -1349,7 +1364,7 @@ DocFreq

    TermFreq --> - DocDelta, Freq? + DocDelta[, Freq?]

    SkipData --> <<SkipLevelLength, SkipLevel> @@ -1375,21 +1390,31 @@

    TermFreq entries are ordered by increasing document number.

    -

    DocDelta - determines both the document number and the frequency. In - particular, DocDelta/2 is the difference between this document number - and the previous document number (or zero when this is the first - document in a TermFreqs). When DocDelta is odd, the frequency is - one. When DocDelta is even, the frequency is read as another VInt. +

    DocDelta: if omitTf is false, this determines both + the document number and the frequency. In + particular, DocDelta/2 is the difference between + this document number and the previous document + number (or zero when this is the first document in + a TermFreqs). When DocDelta is odd, the frequency + is one. When DocDelta is even, the frequency is + read as another VInt. If omitTf is true, DocDelta + contains the gap (not multiplied by 2) between + document numbers and no frequency information is + stored.

    -

    For - example, the TermFreqs for a term which occurs once in document seven - and three times in document eleven would be the following sequence of - VInts: +

    For example, the TermFreqs for a term which occurs + once in document seven and three times in document + eleven, with omitTf false, would be the following + sequence of VInts:

    -

    15, - 8, 3 +

    15, 8, 3

    +

    If omitTf were true it would be this sequence + of VInts instead: +

    +

    + 7,4 +

    DocSkip records the document number before every SkipInterval th @@ -1454,7 +1479,11 @@

    The .prx file contains the lists of positions that - each term occurs at within documents. + each term occurs at within documents. Note that + fields with omitTf true do not store + anything into this file, and if all fields in the + index have omitTf true then the .prx file will not + exist.

    ProxFile (.prx) --> <TermPositions> Index: docs/fileformats.pdf =================================================================== --- docs/fileformats.pdf (revision 678362) +++ docs/fileformats.pdf (working copy) @@ -5,10 +5,10 @@ /Producer (FOP 0.20.5) >> endobj 5 0 obj -<< /Length 1115 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1117 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Y_IpYbOI4uP7>VL*sJQDKN]6[Q8S%SK06ig^-JUHXo\)4)`fne(e3=[b6f>EEC"UTpJnTI4b:+&Q\[CnNTGc/7;_)qPA_)lrGchW__JWg47o`BO[p&Um!+.u0W#O_5XQks>]'NNfml7k4h>AP)7<_:=9$tb55Sr>k,OS]7BE[U-Ab\Y@C53O7U[j+kjGtTb7cGJWt4]4q%1?L1!CQQ<5`TI,I2_)adekIJ>*t/^>pAl3uDLFdf5&^rP`F@@)9W(IcTW(NY#\]*sIM'Z\]8oJGjSbj1prR?4Z*aJdu7J43Z2RImnNO,g&5I3M5VH2':-I_Sk%/*h!,Ube%='Nl=)%igfBIK6kB('./d.ond,XEb"Gj0GB>!mi6:P'nJ.nk=omFh!NY##@\@,j[:b1"cq>'#cGHH=j_*[ELH%0iiFuF6Ypa8)d6R)6hg!:TBoHp'bhG-KhP`1"^1W>96'NidM=<:"39-:ZdRbNHV-aWUlu;WS;@ccG>Q&E%qrkRV5YNNK?0HTYmqU0t*irpd"?qn,:d"C#-YFE^n1Pdh+p.E)6ormsXZ\W*VA:%RP,"e:+j.Cs4o`&ee8aUZ1jYiR+jsG2oQ:j +Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Z:^TSn%I4u(M/f6Qu5V)`b?+hcW?/#04U4=qR5W\?WoeGhWYioMGj;W_>r>%*jBf#hS$N07??;IG:iWe2$GTd%P5A[5AGK.,clStMnIs*foQHm-?;6D7rjp(_fkuW9P8UVE3V0PI;7%6iam]H;hfIlOSITofT^+bJa!4,V)0b+f8okNaP[D!`crot;@qgDZ/Q,oMcirC.FFE03DgO%D/GNrrb][MfLhU*Qmad9XH*(>sh([0>P%hOHi!(FagE2O5c4Nk&\/+QG3O1@heA$Z`U8iek<0JVAPD"J$fgc$)54&K$fAj``m5pu3!*MF\&CN:;4(+,C4&R4h40sA])K64jDS(%7PP_nM'RnQXB(a.Jf#AaCNo`5O!^bp?PMcD>_SL2%%VC(D/5Z;4dMa/&4Fq'2FFK;?W]H=V`=&E;V$hEk.bF?b:[F__"Q'.[+r79T3j?H.7ZaVCIAlmVZp\E0+m>O$/No*es2]Sb?a:h.oZ>h"X8me"Ggq4?1Qh&P;RgklK_F/[Kh3%/q+F endstream endobj 6 0 obj @@ -270,7 +270,7 @@ << /Length 627 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gaua<9lJN8&;KZL'm%S?C2Cpt3DrHp:kad_\,_:4lePae8"7a)jjt/-95GED\Y[Sc7X=BH`oEKQ13lf;+;eN8%gdu#63'e'R=&ai$;Q\u%*B@"V%V/rr.+@u/>BIa&^UsV=A\:Vh8'ifG5q3Se>)9?C3\H`F.gdD%0G]@ZO9YD@Gkc81O#-.k..g@mSH^gqXLZ!g?@#JVua3B$Sbj5-6,lYbgqV<_-MOGp2XN$pVKT[k+LB1bu^Ta/eRg(Hke[TI-QKqC-((aKp7?.ld2=JIa_ZsVQBf];mDG-F`N&NDC3uW6c"b"oVhLM6gO&ZX1N@MHro?KJ^.VU[SWJkhjMteaA*iUIVW+CApDnb/ZVn$Pl\PUMlM6@+!]FVhZm,3qV*f=rP+@@C:pfEP`ehZ`Vc9HN!qc#'<`SdLDYF/=I#jY1@-,bL994*/O8Yk\uNVD?41;XtIn?$2+PUB1'DZ]UuFnSiMiNcMs%Ypf]ahWeDHn2-NmrTNs]D^#'S3Umm(=EpmZ,g.&knsoZT5E*@W+n-3E\_F_O6%Q+O]]%.""h$VZiMYNWT=_jb$G^i~> +Gaua<9lJN8&;KZL'm%S?C2Cpt3DrHp:kad_\,_:4lePae8"7a)jjt/-95GED\Y[Sc7X=BH`oEKQ13lf;+;eN8%gdu#63'e'R=&ai$;Q\u%*B@"V%V/rr.+@u/>BIa&^UsV=A\:Vh8'ifG5q3Se>)9?C3\H`F.gdD%0G]@ZO9YD@Gkc81O#-.k..g@mSH^gqXLZ!g?@#JVua3B$Sbj5-6,lYbgqV<_-MOGp2XN$pVKT[k+LB1/QSQj/eRg(Hke[TI-QKqC-:4cKp7?.ld2=JIa_ZsVQBf];mDFbF`N&NDC3uW6c"b"oVhLM6gO&ZX1N@MHro?KJ^.VU[SWJkhjMteaA*iUIVW+CApDnb/ZVn$Pl\PUMlM6@+!]FVhZm,3qV*f=rP+@@C:pfEP`ehZ`Vc9HN!qc#'<`SdLDYF/=I#jY1@-,bL994*/O8Yk\uNVD?41;XtIn?$2+PUB1'DZ]UuFnSiMiNcMs%Ypf]ahWeDHn2-NmrTNs]D^#'S3Umm(=EpmZ,g.&knsoZT5E*@W+n-3E\_F_O6%Q+O]]%.""h$VZiMYNWT=_jp0Yhu~> endstream endobj 53 0 obj @@ -394,10 +394,10 @@ >> endobj 73 0 obj -<< /Length 2188 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2230 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -GauHMgQ(#H&:O:SkcGe3=4(;ohi]<*ZmaY81"qD[&%"aZ6mU/'.=7Vh06ONZPY'O4MI<^$UnPjK$gCiH:nXq;XQNQaK3@`(dnc=]Na3&#_$nNWagm49aPO%iFCie`(gXiEE/r83J_-Do"]M;9oJH2OH_/(Mgs/!W(C4=mYWPF4O'n`f-r7NA`*1VF8knJ">+C;r=@sNR#6K^:A"6MQ5j0ed'FCSej5%FBEkL<-uMrAK6!sVuUTWhueE?R+8.*JGM5+cK&O"\\Z5++1NAMH[HuE/1M!3gl0m.GG%t3(CM^)0E'Dn-=/n+4jM0(jB"UQ"p;G/$MfgS$ms[(FBdVq$#&[N'aW'=qU+ZB(V8;0L[/F+5C;m4QKHFq0U)qsgs;3N:JeGPU";dG[1,.?B%^Q22u4=`OrHE],24+T\-CFEZs&Y3(EgM`h@t\R@JnOlojW\af&)9*UoSF$;..s[OQ=D1oLV`N_Mb=Z3DT#P@BIPgio.Rl_&-8=LJ=UlC?bbU7HQ7"G"KY35mi!OGh5K%'sQJW%nGJ@3[]2Hs#R/'PH5dI2C/mJrL!r>lG.G4@7H'`pQtb[?sK2,#6k2_`Q4hj(+;^<^'7h)/ShD6qjDQ2iVW"PO)Jgj.KX2UBX6R27pOs2arhs09&W*/AAOqhKZME-d?WGK?:#?L7MsUhRKknKYr;M3b.-Re0F2!2eXbEBXq]KI1H&1WF5F^*5VCPg:(U8h.G_3@Zs],l.Mu_R1OG/Q*-8I;.ZcothU9fb@B]2ELJ>:'r^^'q,]-sRC>'9^35_J!22pTiMXLh8;OSZc(pSHI'aC-)#L?cHa`\:oinE=0QmncqldSr6#h(m2,>8i%X=s`SZQOO_YqhNf"^?D(_''F.&=Tm]LK_lpq'gBhOhA`_N]Es/&%#+f5!`r"KJ3^;;pB(UdV7)06UM<'!6b6$YYQ1]/_ABao59+qOD`ZB/O:9k-HR9\Rd<>oRm"VuX"W'E#F>XAVATAmc"]B6-WUHT>&&2`ilmX[L/+AI?ARF(NNkF_Ih=d-Z$c$Za:]Y/b7bb!F::,T060K*i*8?KlPN-D9KOE'/c?p]1bMYPsC'U8#aF6,R!shehmQ9P8QNG*"(9bP(#ARWllLh8"62N;oMOBRUZ-M7V*Gr=VhJF#,K5iJAZtBefGn($mrRI+_qY?ZYj.!@il:#nS^bt>Gm/Va)\nO97i3aFT!SEnCn;T=ZV>KLbnjg(;(Q3j^^=T,-Yn,82L0ljZZ+H5u.Z:+sIQu@YFFRc_Dfa@.A(Mjs<@dRO7(%a_:u;8oFmVtH,E>.:ol$F9;\tu1E5AbbkOsmQD%>8TJ_ +GauHMbDt=8']%):B\*PEUZcF6h'Gc8ZmaA01"o(F"YJ+[&P7(8ar]a390Fh48u-9AK#,Ze1*?71GjZaRG5^oZrUB3jGBWQO_o'oD4_M$%aM1U-4?r^?dpUh]4T,$Ep?q@P=0^cjo$r'`i3f=Bq;XQNQSq4kKtHguB3dRu5,+dE)%u_0o,P-$4^sZC9++SEfP[0$Nq<]qO%;.KU$?>L1n3Ts\HB"TmAIUmtGX?m,9FdpWoH/RAG2B&I`5;9D=]nrlV7BO0[Q0JK\SD/gC6ga(G;4ak$7LOs[=\h.uC]QB@EGPXrD`5@+M18#0,!g);(HX'9"#SYB(7WF!5L8>nOfK*XRbHbia5G2XZVki$4g>$0D,Ah%?PW%*u0V?TLL]Hlu>gak(!hr`%JlFaZJW%n7LpbNeeiQ_(9?_RjdI4[Ag_!@P%gP)PeE4[0*aW>@V?s2ar(s09%,*Ja#%qhKZLE&rgl[un3l]\)np8CMg?j%"hU'.jmNFjYmu"C_-o(?ZpY-YT6O.AJ_Be&C=PA/IaQA5SWgMFm/(8[mXTH1a-`@>RN$jKB$">:Sb!8]LGdCIAcRM%&;_4;#Q3)tZV'#_iahTb;E`Zbj:%flGAKNe+g(n@"'?<-(gXNd("ner1eU4mr_IjL\_?N6d)2BZhe`S[-!KSL9dmW#7F>>R1J`8bH0sDM]YPJrrbZnFNTq*0;`;B#t_j&g=rLP(sm_KQrm=`]p=ghFR$[QD)=[:"7"XqLoUdYqo(e$tP1tJS-@;Tsa]l'1m4Ho^6Jn).Lm,Qk[Vq)TrF2$7M`dn5'22IMg2A^3&q1M+G?pJIa_OP?MgJWNe2j*BBe$X"mjgbVT.Eo&k(QGG4>%pf22Q3,)KF1I%;7"fLnY%"m@aK+m4_[`/E\p\4d]YZp%GM3Q5\9'/DK>rOR0K6jV8iC5j!m.FVIoISPXN:r,)PAAl=GP9mR"T,&/e?[R[Vlu0_DS*L0XKceN(%gaAR,Us\cO>/!!_i_4bErEoM'rs]A[V3Jr%MrU$#iVdm55bTXXqpjja-KLi(gE\646lmNIOdMAp4'V[6_484E=V76+#Zh-F\t'O9aW_TReOdGI)dEV;@FB0I+4>"d;?Xt(mh&8j%p4t1hPJnREi0o?eOZ;/0*D>];*i''+)cGrAsO0p64Td,h*74OHBDn&LJ&SPTJP9V6P-9CNYe38qVnR?Gt-n[H[[7S?L5k3#J%E*L8aaYV:[CPt&X0H8-O"lVS^f/_cK@)r?0'182fF427g@e`rI*4nkcZ=tStpUdDRTnbG9I$^(n/Qi7^Y?HM?/QAc8Iru23\[MI)DT/SN@J=A&lRHggWXFQ(C8#FMCNIjgG[O#F3#T7+!>.JtOT~> endstream endobj 74 0 obj @@ -409,10 +409,10 @@ >> endobj 75 0 obj -<< /Length 1983 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1980 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gau0DgQ(#H&:O:S#^OPo2BuOM",[)J1`N7S6diR56anIWRC7glU-cuf\6n-eCb:EGBtI(u#i[^UOdpK)k0-Y?QEteYg#j4^[da=q/.5#d`,Q3X,-p)B1sQ@7N!`Ul:U<"'frLSjTF?9PDJ!=d.YN:.33S8XM*hk+pVH;OYKQJd=Kl\4Q^a^KN>o$"WN0l5D;A0lh08+t2JTj*#dG6Xr?:HQ[!TG`)Z:sYl%p[S7b7^aE)3WC2.%Va5M;5YD^Xp)%WGf$]VOHb8-5L<_[IhQ!4'4*g,R!m8W1:LW3sF+9,C1COO!ahK5ZV5\)TX4iF[(DUC%<[?64W9bk_N8d+];5&G)"CmDQEo'C/AAEZR:I`lk:b.>Dg'\-/.!=>,pP&HdOloe:?CQ:+.J5iWM?BPssA.>S!/i)'s"3CjE%=>aFJcNm,MRF%LppS6B(Sq6g&S5ulBKj7DmgQI^ae3@sj*CNoWZh-lWbfKAf>dd8Fb8a;PWW6Y].AkbaeN"VI[f4\g162@U@9hdR_#fYXOFoKto_Pk;EZelQN3+tJj"BIdb!j>L@U`15[3-\;FCSM_"^msW2e!41g/Jp\o75'"V^4e[tfBo3=8Ifg>]'P[HYNubT%420gb\5RiANc;h69=BBR315Y+RI:LE!?C=$QS&(QZNP_S7^hJ0EW:Dl)\'ERdr2-NXa5!1[.^UjTUBn<@3qrN*&ncGH;I>q>63>Z?Kl1.@4eF!Yg[i@urL[^>^"e29`>8[C87Jc.)I[==r*97t#rKBXJ-H68[3.?Ot#hR?DqTj2j@<"`"n\phdH7jOU84?erB+l5GP!edVi>nE53eR4TSISRfnJY'#'JTG4iih#R@:duEH@Ne0fLm*nY'V%EGk]'LRoZa@8e#57!UAQ't+C_'>ooEUA0Uc6=0+QsS`q`RuA@Vl0-__R!S1:tZG-SnN[fRO/q&acb]Qqf7?.[3tZ'Mlm^;i:8)\]>NmB(Z5!/KUA@*/iqe?YaM0RHSdfk8Kf3_*_"L%$Jrcp[c7J*,gk/kA4[$N)OqGj25/%p*cS$B?QF"[=k6WI,5,/7->(C\XQ]h+fWgrmIG^paW[MlNr<`Gt65+83_]ul9aN'L[+a//Ep40W_HfnYiY?BCn'6rgGq2TC-M""c(L,GIBc^rq/Y/::o6:U*J&-Qpm3W=8_)d2N9=hnete]UabB)<,fCI[eL6YY_"I)GefXk6NRsPX`WD/o>R;,:`I>me70q-n')1TUi8ME:`>4j$Qa+4FQ3m2j;1"/37!sJe.K#]@:\D>=`>W3%P]qf^aHK',mL%I:G)j@5@j2oZ*";,8kGKc%2WK])Y_1g[q1a.0G95K#:q"?<%JQDE&,mm?cjYBB)/o0(NW)sJO)n'!15[+k@+M+1bLjmZ9rBP5YWSNKPTt*oNKrm.qfZCVp"kte2JIiB(d<;YPQPc%8?cMH%/qQA!6g2m/'o>U=,c`8!#Uem,6,)HkWkVNVZ:e&S[)L,OT.X-uaP]7J>cdoQ\,LY-Jka.h&jt>[M29O5DAkqhMk^9TG*H8^f3;OQ9OB-1e1u>[`kJ890%^:Y423+)&%](d1kr'9\T;]>J@g:2#*k_u~> +Gau0DgQ(#H&:O:S#^OPo2Bu+DTEpXTh&o,uUoiB8FGka:Bj%BPU$-XSYOBi$XJ&\M3lqR6GYOSMkF@r#1Z[lpieR3dj2**^'"aa1s8/&Gs+-ZXN[$@#ro5YMSOMNNf*MO$55d`r?dXC#cZc1(2N+1DYLe[K[uj&NK_96A3nXR8J3W=@YPK;6&"Rk-r;#+q2pR;OQ[+%L(LeAtk@It22pPdUqT$llH=#iQDh.#73".GeKF)(A"bB$DB7[TTUVr5)c!M4)\DId>Do^g+'Qo\3/JoP.HMl(/YH>l<;5s*%T&1b4C6&QN0@?^R7`Sd$a3d&:-Y%Aj8VsIll`*CBFrm2_o/>LnKJX8.$r?8*=`T5+gPRnSq*o0p3fhAO5PCfi7u,Y@)K5YQ/t;]f/a_QY+i5?.Lta0@C`;3A"/C&;:nU<=1&tbbq%dn78\p[RG;k8%Xfr!>Qftoc/dgIBR#/J]`=['>BdN#H[8DAX;(!^Wc;G9R&s&8b(FbplXbJ_)$3,H_m=5]XG/HE/"fRg7=YiRj/@Wa@Kn4lJ-IK;6&=,*HFU/>=rEY^e10)>3W#Qp6HlIcf*a#$Q[D@?Q`=dlh`c(cEo]K4`U^ui,!^"8(opI!l3A^pX@=ai$JBRE@)T-TacS'\n^OEbGOdh`pZp8('3/R!G2c\6pg,+M-"PRSrGg`e"F?$3[$D]2crWji=MQ'_RhLDNMnT=A3SBq]^:b?!R%R-MR6hWsA(:!LYXR4/P=&Lt1'`=]S5doj&?GKKk#nfKd63RU%G)An>a1,Ir/.'N-'T][f))_VVr\^7GQVc\]?=.kq%$rhHW9,8H$!9]/OlE1T16UdV4KH']c`%bS:#d5HdLk"#p&#p+ohK6Y#6=I7_%X!-bDnSkeVBR%c(%8He2b>,Tbn)P#[]8=j*h)iM4V^1(#fi1%didS[sSEQoaCmB2ZZ[><^@BLu3h%BH#`2X^7$?n$GWuoUjLZ/.P31dXJm-=VQAh`e10PltN+QoW=]s@75^gqclq'^aCu(.qn-r937`cm2PkiH&O!N%.3E.J(30A;`Yj[8Oqo-_q?Y)NJ#(#pkIo)GEoJFR_nT_?HQdiP5#qk;`J2TX=oa?d&DfDS8S`8-^uU'(E:he\T'0;l?6(Z*ejkOD\&ZCBV'%!`cO*QE+%Zl+J:;E,A&PnBGcq@5S*]$7qEpP^`9\rZ4d0t+qY^]7n\NGm,8Bi7!)?j@eu,O?*Q3hOVl2P<+io,Y&fDim^\%,cI7D0m[1rb0?#c\mF$L,u]*?ZEs+\f=6?$DT5Z,Q9Ql,=_7`g9f,NjWR;elCan9Qs'@SmL2--\`7b<5NhsJ\pM:>0g=!$Uk0^FZ'=_^*F&RoDGLR.Ot&;ar%f2Y)b22L(!&3_9eAh'aBN\]]M[/$@6u=#n+,Om07^.;mZ/Y##OM/4rip9X$?*tgb2("WS=Bs-om4`!8VteCe;LZM4l9%^>4*62^^UbXshjHhQ_Tk,NcSr39jGT)^+^sj'V,C3qdjS4h9)ZVWU<"6*GF?G2;)hGDjI[?Bt9F/JiC#+2sG@S,~> endstream endobj 76 0 obj @@ -424,10 +424,10 @@ >> endobj 77 0 obj -<< /Length 2356 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2306 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatn*968iG'SZ;X'jN(A0giTEE7nd%9KHIdNLESrKd'C&Ae`C]jLG$["UW6M*s)qj3YU8D0;3_'mWV(VK^Vs"T3$qh$^0;G^E45&Q=`^[kNXi>mItgVb-]C`UoBM1Mr,?>JerCC;X+Q).U8puKFmhPNY^oS6$/F89RWjT7e&l:mj=f@fg`Q/BHaLYP2onOe=D_L-^RMX*2C\$)Xcg/JIofDmr=oHcML1[Mc&sd-WJQJ>NEZ*h5;DPlX6n0!1B\$5Fb-B_\Vt4\(C=bPN^AKrdMSk7+l^RDJ??+uIjkX_4;@7@.>f:'H*;%COC3-Jc@^hB9p%e^1'*JT^n>r%JQi%ftISlM5q%@3",[DVFl8msnGQ@^V"icnL`"u04EiU)URGJFRq+ZV&qisr:Ed_#/cUcYgml2J'qU^Kc0Q>LV,UUrofE/8U5ZBt83*n#$G6?pa)9iHSc`pDDFdTn:1k`^m_Bu*>1'oAtgj+?SE]Y-$g3aO4ff<)#fdW&EcGO*;F]Ll#kE!A-h-OX#*0E//tp2LIl]c0VEdLdj#QXn@H"sK+"cQnFjj)kn/V9Ghnh"+WZk;HFJ?TF=.hJh7rZFF=L`j#GZDco\+4cIF?ZJetp(/2"e)5$PYG4"eR[3J.1oS;Vs)HR%Cm+*(40XuSKgDs4oj+TgMh3toe*LB3@[slQ4)iLpA=F8,8*]%V"UNIb@1i23833:\/]t'\pPO:@6$ShlfOglruj0Xr*T-hjjhO8;P2e2&]k1r<1Uj`Y@WUXQ_SG>S2e1>AH'm!:)#G4YgFQ,];S`1bk_K?EiP=/7KLO+l%uo.s#\_r4EbF*m^L<:2V`7!N#b>2c1FU&m0tVVuXhCW&E8VP+#fPAt2&^(7r<1UmqQ8RR`&@`(g:RI>(s3g3_iqk$8`$&Y6=-K".O=Y"$Ldp\u12)Qd#jWFcn/)G67>TZ#obk8Im?h0@C`k!8O;OZ^LtYuh)Rs2R"OnR65fS]V$j9WW7.%&oNIenA8Z5.MKQSY&7DhBf<"#<8FMR^&(\,t[G';/D]ebJH'[S1IsDgnA01u$Cl[EIgWDO_3IZBmWmb[3XR4-mL]*pPLSsbCE,_BrWqQ,!4fih=rFTEecGOD[U]#XGD3!ANa.'*6PSm-JYFL^JX2mo$,gCaXrJ,lM8G"^'PcJklB.?oZAV)o]qK?!eKMBS*ZEt`RbG';2[5ksN=?!-.cDW@k1bErlGst>O%rkq5L9+(:+Stb[IG.Z.,O'9U5J,\><:=%ZS:+6`XZ,FCEOMS;p/KQ]pTh3urL^.PSTM<:DAO9T#'Ti-pOT]sDKWd>JeVe=7=!RCgt@N[kGE$t.pG:HP4FcC?BXiC,?mHe6:p8KD8iJI@A_,4j2"Zak6L1(%on%-IX#?um-DJSma"Z,N6bKeS`/:OqtX`MIUfbOlbRkY]3:9OnSgHOpPZPEENb)Q/nlMpr^3pu[HE43h>QSX^!S>E79UHe9cX+=:>PT'51\KRhqjctYp4VTfR-tsHcVZQ!L8DN5;%V'OY!?'kF#j9B6AtP$^:."lhg[>'i)Ru:GSi2(0i-YH"J6g>37#k>ZG^@It)kDdHp +Gatn*:NP8K&B4,7'KeE42,+&R#p,R0PY%d.[T7`hHVc!Ak):lPPT2(.^*'[9_*7uB`&a)aUmKHr_u:^B:&'1FppaLT?*NO!s8KAROuS<(/CT*GZ?^jM72?\2(=d!gAb#ZW^%[+Xb1I3==iuP?rKGdf,&+5QoIguJ.j^7_,`Pi#dGJ%&?2Q>O2d6/8L_215:GI?IhAtKBf=ZO8X,jm;ITu4-XY\kd:X>(JXYWXN7N!!sM\ot#oek(g-%j't==*f:?SdRP-MhU8=qs(b(:&eJEP-5oo:us$NG]E'i/'j*JJ09tRrE)*H]lE3-f*@709`F*6o5hBZA^GUl4R-t?tk^]U0DsgQ'3+KBe$FM=B>+2lD$!sNg&H.-Gt.AI">4dY]A4d]l>KtZY`Is#Z_@[jgNt2G?_gC.9Br[1VUZ(:0>2-KFhfpnZ.i\5%pM;6WF6JN1`Vpk'T@VDNj0*D?E@t6qjgPR+>\V?G,NcS9L;")15!$.ZJD"AJZSs5d+eVXRP-\%6GCX7%cE3]]h26nWGHX.T?"Y6E3Z)]H0u72E-$sEGjrb\2_2$XDdYIs,2USYo-f'r;5bD"d9FFnR/m3g_QJj=P9dr@f!]Ip=KE.R\GcJFp4*A8,DldF:>FBB=?h"h?*X]UC$pY#_t;^DK98#+g,.+h%9W]t6hg,k=)#OAl25/:bFB/m\\'A_BV%3K)1+cI0TQFc#TQUNqoI0sDq:l(T6;`>!BZ7()j7jK2_He'5^/47F*BXC?!qBcj[iN*tl0V4n,3'[b*RnJYa%Ue6`\$l$SD2XN1o6(%U*M_!AL&n_qL^qdgDDJcR+oY`Ed3'Jbo.,lIk1W@L.qKkBTkso:&BSHVgSS4pdgoT*!$-L-b?^jBjX-!5/:d,:)q'T8EZjG+cI3EEH>jZKJ4s8_KU)i!ede)m30=tAD2f.Rm\)Mm1\9Dp16I&+*UP?CB:,MBmkX9XI\S+p>=S@4hLm3!(A$M0!18'Jb>4'K@$`k@jB>T>F7(:MM0MN^&[JsS38Xd$S6*LkZN8j$XABZ#1;Wm&IS7-!\]GF0;K(b^pW[J33,6\%'H/bf(Sr,:Cm;TlgP'_&Kct?Po3Zf\79kNKQo#?d13#^W9d0Y-3:^$V_hA(6I)sS_NlZg+'A_BpE$:lN+,R=%-X^=bUiY"_=N:gB!B)HN@NCb'3Hru%C9dLi,%iCfVl(,.&(RA#'^3*aJ#g#SF_7t0HEPH/U"\tHPHPKso75ibn8PHM+0F^_b22`KjkX4MWCm&]a5am\]e)2?D;!rDf3"t>7*YIjZ0&Yl$5H#&I<>IDIsd-tZ^e*nEI)qs;g2ChKsdU5b<06C65HFt//U=OkT5Vn*'ZQelbaTQCbACjOliQcjP!R[mrr@_=I-p[AENi>IG'iH9@DG'3ni?XZE"n3XF8JFXZ+;+[^Mn-qGQ`>p18%*oq/;H[Bd6;H180\49g!(?hY_oGJm7CJ=R7?)HiSR,-uIPp/nfKeL#RJjAE86_s;BW.cYXLcd1q%6RuE5a$lTia:eC;e916Do57c]n"!TZ_fmL%p!`ciCC7Z5kVVoZYZt)^8^(b,8iE*D^'CX-;Z:N]hg_uf.erY+XO`m(WJnF/OdVGROi^.j\pEYB&,YN3F`m`2_O!39EV0j/X?5E5P''8F;Q;maP\Z=upNO[0F`![PmU(.los&6RH[`TNG_%kghtpe%Q\VmG endstream endobj 78 0 obj @@ -439,10 +439,10 @@ >> endobj 79 0 obj -<< /Length 1821 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1900 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!;dD/\/e&H;*)Tl3SSQkf:s]``#t]$$C"=`*e(;ZsI$gHm46V<#;UfC'tXk0^%E#:iUZ5nY20*UfSHmWd`\l/:B>n9%!u-2bJ!`&=m&+:-o/kL\$ILD%XjgmS]O*kZd_l;o4fU(0jj(B_9pabCmPD-uoU'%id5c)jbhP=h^kneLV"33mhjQ&0.&S7_9N&)H]HM02b8u4`tKA$R)E_h+o2$A-1-/+j[/143'4M8DN$7PJ+2#LHYW*"+`MiBFV)d,`YTmkUe"#Y0R)P%3P1@%01oQ-#Cb"\=jM-5U5-*ZorQ?(>]NO:,qlc=H?Q*\&Iet;=bfK>/OF-jgn$X03)VB73L;D987TbFnkp!Iob1LjisFJ)>k@q$8N^>fa^gj6_1WPWW/N@`1$"@G!-=b%MU0U&$]r/#/7_pmJ(%nZ^Qp)&-!D`5aBXkjBiVu@U2=i(4kW)$j[sD?p=n;G#l'D#dc@CbZpQsg3$:tO#Jb_6WoXpqY\7e"Ncn6:d3NAHl@8paLrcNHjZ&`2XMdu7=INZqbf$CD_6i9=#"1s+Koec$Y6C/uD)QL,MCNs!jG;QNF&9TW`!#E)oPp/^sj3bg/2B5u6Wg.+ohQ,u`Q>+X"1T&.EMVEc`l`SU?$Qc:Ye_1):mWhkfA1$->!HL!n:Hr(!9g1GX9P9?dT#\$R^&.jOqn?7D9L'fqhI!I]KQ^N[bH/*!VFGEj\J`TaqSiBm9Nc)]?%(Q5XGrXP]dVbO*7c[6kT'mCa@,TmhD?[chVJke>_6R-R5E'mh25>H;\p;Vs,oDUVd-I4%]4-hMe.1JE4h`.;h-,H4%7lAG7u9UDdaeM(a,292UeEbmg6;L9Rr'bGVL4;!M:TtN>:Nf<76C0E?D?HY)M1jbQ[js?AgI#`)3rrnG5VsX~> +Gb!;dgQ(#H&:O:SkcIuqc%qO]9.pYuRlK4^okn7u0A.J@A_InDM(U+CV-i,BCmdY[g,NbrTEmFk8SL/*k0/O,3?>c(%fRMGB*j'+#)PuX-O`B;5@Db-O>.A/8iX/nT7`J;qtBUnF/T5B>^)Fg`AIO+_E/9FL%$ZaZE'PiBn)HEEiQpF<44V8lTtdK3-tR>3Z?"a.*>N7`EZ3_*^LRhj&)\R=qBp6g,Ko1ZSnq0,\9h>]J/\OBRU$FpFt.I+_2jY[OOs*m#17c2O`,G9T2T>FXGMAGfVT;A1<7K0IU]F,2X%+!$Y>\h*??q1Z7]UD"\`C./dF/4?37.k#qQ5YF5WUOHR,k"(8i+1L^\!=L:)&:HM+VBMn8@F[Q7WSLo,N[mEQZKb@Bqa]:%DM?9fD?O:A1Y.I*!dTHfB`uHmp7\HLmrN@__?=o$M1#("'^8(9K+YOCF_cHT,S1>+:rW-"$cea^41AjGR#]X8YAs=T_?)GWQ8m@coV2eck;/]Y[V(>Z+69aAEO()qok^8G\u_ec-VikJ).Ed8%`'JkOd1>(nN9asAP%TQR]&.`?Ci7'#2THVBr(jG!iNV%(2.DERb5jXTnhH:XYeAJ?KIh^Aq_)I\D]f5ALU"mg/pJ=1W[Vt#aGuH/&@3[HeW\(=3r^&A9@eQMW<)$`XT$nsjRO:FeD]_XfbKf(%MJZIi27Yr96^E<-(a1\j"-6#7)i:p:FIL@iu)+/h`Paes:H8CZ;:84_[@;]ls1RORqd_E"9%[h\dX.;69M_e//k?f@X%d#f&L1`^g^t#KTP$\eT?:f8hCcY$.p%\8@No7eOiDh,'/U(Ll,"!j endstream endobj 80 0 obj @@ -454,10 +454,10 @@ >> endobj 81 0 obj -<< /Length 2155 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2035 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm=D/\/e&H;*)+nSEk+]e8RGm+DJ:>BGsSLsPi!V9^G&nPjbV,W]>359p,/;JE^C!4=h1_;7$I.$C4j71ToF$&W6n!Mg\s8Um=)nM_gT#^jlDXlM)D--J=N,%t0Dk0[:J,Wm?C8Su-9VRPEc8,/Z;qoW?/_r3&D6hal]!u7&FT%SEP&M8AkgcN\[E9dK^(<2_PJrE>dVN39GEW6k4O#:G/DbT_5Dd3^P5CU"hqI/S)@YBMSHFfohh:'";TupkVKaHGpGmjSjfoQBIB8f`ec6i9L]hcLGcEt[Q#l\F5ag!0J'2P/\g*!N<>N2>9,#n0lo%MBnG?2#&7_3`om0B:s)]a^!sbOE$UXnr>cJ'a.nBd.-mguWR\__U&bm;`QJc'MhM3!nh*Qj7'F.@_/)8[>!S&+^g'/e!#=J1WSI*7>SHdG$>a2MKSH>Z))#j+sf$TFd-8'k&Y0(rVZ:id&B5RZSQqS++D4e-MdB.*rgc)\mbCUKN0!!C=o"T`?W6MY*L5c_*XucRL%[.$,sZ'gYe<7u3KcN5plHnZtPJA@6.Q\5\\l:DR>kHjQc(-n(;,j!o9a"=fsCD@N?gU6]"n*5Akd`b%Ah%L0n!F]Jc-a[r!fIE/>fCUfNG]]6UJ`,Fl)1CQJop<(XLFO81D*XN==10@D8E.dEuGG1iU.%Hs5d#K!rJ\XR7b.pPIdfZ+:@8rnW'hQlaC4i%LB]u0ieM&;,`Eg%eKCssb#@Gp;hcc!*=AIJ*:d[.8cS>GV$#4Q*d?30"9JlWFk@t&J\k[ERC<48&Sj%]o?YBY&Z)/dTm;1FlM5D9=CfDOG?HQR2#4+%tnFDI>'Kh-k(r`u4cUjFbSO2!u29-pNGR&U(9pD,8H4/>C>nS.K&0fFq6%q^<-ZpDJGNQt$E4/`E3_TAR=Gn=i%%0fk-'B=R?>b0p%QsOUhHn!NpeTV1pctC'M5%a+P[[pfSP\XIe(+QF_!e$bAbBqf80o\:$F(?N+ld87og;d/bYEj)5id4`DSugq<)J]jT^k&_60]B*@lQO-)!.JZdaaMM+9L1FhDVBLQ0q(bhCu`O?=PeT*;,/B]rDn'"S/NuW-Xs^(2COL&0VbLLTL=7EX;MebC>I=7Rt.?,aD(fMD-R\#%.M4L/Zf2g;Uob-9pUTL4+\;a2GiafWZbOr"nS/e6C7h;\fkB?Ot]mqqUEQ_O=D>B\P\qS0`%R;9&2X=a%6t!&oi=uE"l'#;=0BPWlhNXKQtL_5Zpo%q8^PkRkuL\]K[q`(/L7L:SIt&PVt;'K':$`@Y1>r9,S>Sb$PEZdL76V/^3k:83"MsJs-qMh*'F/p6`6atk1IPs7Bc^IbUI7O$Y($&`D!cQWp!h70\`T=8j> +Gatm=D/\E'&H9tYYjT[\>(qRD>`,_Eq.I?oc25`pleS%0T'!;s(?*DR?",UL96H$g7MH]e!*9mHulDIX^\E541b2ZiJg-d0(GKM8H"%jC+8R-Rm2`q5L*O2>5Lr3rES$dAa8ttk96B,aHFE2'7ZAq.HO?k1sQf9&$n*MkL/Hd6amQKpK9FX^*Kb(er(;_QNtB^I";IGmA`91+?2=UH^\d$L::a0S9@C]%`!C<>69bA(g,#sf*'l)!ce1KnnCe:Qr==l2I#0eHrVrTO+W,M]r1%3\"h'L5PY)"58itdK[Lb-G"\Y+^:r16?AA9T*7P>!(P5S]861s#gn?d-?"bYm$5]W[ZssGd+E.l>1,'>U>!N`nN!`OHU1bH(Fc[9$%8Bg%:0`WrEL3cF@(B`#_"1$oOs<&S;:$2S<'rjDgPGkdp+(/,iQ1YE&l&AP3DG$ugN^c@L+5loaVl`,8lOZ,,pb:HkJJ3(2!0$0K,i;6=rR7>%T%qsMDnd^U!Pe>^aQs_EDFrHlkF!&p9!g5Cpg"1*[*59bLHWBQ?S?F3=?m)YB$M-Qr6.?B:$]T"aM3]h'uR29!IpT\L@+s'Y'g\M&#)#16Ct5;f%2G(Ld6<7+F.g_(7rYDF.nB-#FF59N[02Bp><'lmOV%.dXUj4Cm[QXF[)C[Q.#m%s0^m8(9*Ng&g8HoN%o&#Z,co^.@I%3C<-Nl=4l)_GUW)RoKg]GRmh$9P-p''7Sh#PF7rt4S3Eu"Qpt^aK(M3,#PlWosRFm]7`g*0FXXIeb$"Y'h<4o'c0pEpHc@n`VfkHVrp+";u3T(-PUD27Xh;;Z5^#>NLh:\bnC3c8E5\[++QM3G!c0XA%=3O(]eEBS;#J`K1]MQ>WaL$#K_/FA7,R%1&a8Nh)S5in^Su/67E"395"[gnu_Ft[N;?inb$NTe&nmkYsJbUKn>VOX<')DFV*-FPN&_M"*J<";Q7<4Xc$r-M\U'9ECWDqTGMBIGRL*8Q*9Lenu8$h`tH7^4FT^\bPe,jAlKe2rUJ9VERbXkN?h3Jj&HLmu'pN>03H<"jbt'9f2,WNm*Q.%W3(A$=XMlU\H=*Ip^t-_shco.6kol]&hupjFY8S3E(gGA*\!8K`%CbnR`eLYaPMPs-fjp/^JUU2a,W0oT&6ND4=aJm[*2c0=s'0LBZ(3]*JG\0u_3h$s/D1Qalto0NX3g8W[d] endstream endobj 82 0 obj @@ -469,10 +469,10 @@ >> endobj 83 0 obj -<< /Length 1945 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2006 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm<>Ar7S'Roe[&Fu%e%4b?+%2]V/C-$+Kq?lD)]lS55\$Gf%]H9;9V&&8=495@o\-6#AU:2)*D!Yc:lCu4O2Yg8e(l,(>FTQ?@d9#NleX:0\oh51U\_?!uY<(oN/+aPXoYZn]*L[*B5Dg:"!8.te=9QPdUaF9,WUh$JZRg:WXZUtpLRc=AkbZsM&VTuh,`C*EAFZ>be_fk;K)ihj#6i.Vqk5#@cQtW>,<\D\gX\LbD>tHk,$oL#I5a0P%Fr^<;/%X"$>Ta7766<"!D!>(%R5+a!ql#Ph7e]Hm9F%6tHPf3ZS"40BY9:'@ik_Mo],fF:?^_$f5"T[X_3mkKNp-#<8MgW;D(Du\Akb[iUtG'.9eA,9Xp9XbS]0bY1s#A8Z_EC)o2&o-3%rEF1''hf0e[iD[Zgso1nZX#SN$SO@eehN(G&R.NL@YR\O(bjL$a'[UKS:bSKZ^.[lft1$b(7Sebu%^*%"2JcQFQ=?:GEMG3X\*J@'Eb5BBQ!q.U<*uXDL4car5spB(.`o>,+t+4W9EjtT*acV,2C_KX@ZB@0K?73]o+[,A,bO_HtneF.!M$j/"JpkFB2gVeB:g'\&Z]rdUpAW<*)Y*3H9O0qld0dUD#-H0RFFVPu%#Tm]k2tf=9!Yq1!gcSF]i2?8/^#W'BA5((J^&"ha/R14FslVM(-Md'\3UYKc:%"`5Kmrlp0PW`UDbr#Hn8IdTC3tuE:f8Yn!Q?,lI*oCdWYG2(CCB"V,RtHSs+>u/DEfXg7<>HcYd?9.RH>qg!cLV3LI0NoDUQ1%O!JHm+%[=hFN08ND+qLLjDlc,<'Fci`Yg>c[+`tkUd\oe@*1$'_X.MRg>HMf>S;69,-rHS@5JX.d[\=i9nZp*,:R,.Y%`XQ#I`+r/%j-hWtM#OKn?S9hok=[k5^;1FDM1AKIYoJ6At[Hp\HS`*&%tj#!OMi:IDL?O4ZTWaUntlb^;ml?lidh1B0PYPk,r@FV*tl\E3(!bE)fM!n2Lfdm:$O90.7?%>aZ.[PcCN3fRs)l:V^NuAr*/keW;O1UE'HN?`TVH1FMe-\eRteKo"6AY$`IESIiq9/rkqElb,o:jhd+u@3BMk4AFXnd>+Dm5L%t)=ZoN%6mbB;0;7!>46NP_I?T@KC%a'GK"GC+Z<+[lZY+"tF?n$>"C*Uj.`pe^DF+%rrsFG(!rc7Oara,t>s?lU2dcjp\6h>".olA),8qjH3irDd(=0sn$[6pKn\Y0\"0=aB5"YlVN;!B3]L;Z~> +Gatm<=c_;q&:XAW&GDq>@$_J))_DCBRr4Z=8CPLj$Zq;YQ7/5Y%S);frq@F)Q8OoK4b@LS=cq\uo?HgMkk/udbB!,q6*3$B^0O,bYq=l-iIBJFT!(;t-e+'U8m&.5+,ea3DP34,L6fTeodn8Dbq`SWr@T&g;/=hK1#grj[EPb&0'fC9`!bn"o`nd"1)'=;gi!=EgMA-]=c7DTMWP.#Q'?:Cc(V,%=Nc:ij*-4A]U7=1lB09ZmmJJN"'2?4lUj&?UH)'FPR*.e.gkbW_`h3Kia-D#06B`ECA:8/U60#,;mnZ+.M8"I@^9gtjt#dd=SS[R&-JV_GA3$)UIFirq^Q]^dU""piA7j3K"Ui!-+Fm?"g^)H(JY^2c=sgqL_p[timDZE1-K-NP79)Qa*6Jl1it!Kaqk27!;6:h:(5"r+/T$a-jMoWVBmNH&0FmZSe9a@l$&_^#(8%IYopOsmBS8uoK=&oZ:4&p_#d2P%qMmY-deUm]MIeMdC]cfG_uei;[33!9Pkl;d$SBc/tSO%hM]F'W4XD%`k#P!*pkFL)21\415;b%1$0KL3/h,$_XXT)V&b9Fej=15:hNTXap.D1nltIS`=:bm!P)`T>%b1npCAO+Q[2G=8,Q9f>tF&!UitnNGpT@6W>\rJ%hVYgN0b\8m_ZD?+#,:lldS%Z$S5$E?eWV'd.4&.7>C";ZnX_H_!jiH)o;7`jq1.m8qG8mI#Ej"p4*MkjpL@uj`K(^d"D$M-i+BJ&g-p.Qbc&!"R$_KgYCBTDXRD*Fkl(..2uND,Kg+rt?24M;VV=4-br0YkC"I.mE$2uVH>$&S`;]A!i=H@0f6GB4L>eBkA`rpQVpHiZ@V"!CE5q(0U,Kc^,JJUddPU(n%"YL>r62`>i5M8$g7sZa3P]\l'-e!-]k;`)]K>GIqsPl1JE0k6I(mPH"gj,Zg%AX0&o99mnW.Crs!g&fKJ.83eU98>akF-?@A.<;5U;R79#"PXWo!Ncc[?9=q*`rcT(^n.Wds$-'GpMrD$Q~> endstream endobj 84 0 obj @@ -484,10 +484,10 @@ >> endobj 85 0 obj -<< /Length 1375 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1602 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gat%#>Ar7S'Roe[i7j]oAk?8ZC$5cFm8B_sMJdG2ddBD`.@Z\UH5+mhrUlp<2@jNEFV#hG+aL6gc:;ocRf0L[rAUKbUOV1G14fg9//J)#'R/I+3(Pc\6R3OqR/JmHNX>oe=\;$1rJrAorl69W&X"(i4o+h61qJJfj+9a\LKCqkU7n/^Pr$iY7e@3[K5)+[N!*SNQ-ic%5^c?H?E@P4&\)C6X2CO'd2eJ9\eD4A2!_b=+tV%Ff[g&`(-=n73-EEVb708DM5Qs)Llfn.;[p:=ULbfG22S%B\Z6sD/Qbj0`QK:DQd:1np(I-Dr!*)]L].SQ=LRR0;;h-3<%t'aLVA;&<%jWFc0U<:a'?M$ud@bpLZbli82rf-#ePU`jK7rWf,JHT^[/=<.4[MeFW;I0oeHc`9mnScY+^JU@9B\tni@WA6H7T0D#=09,g9$-di2*1.s?p6Usebh0lnEQ>9aYtD)h/J=-im[I>Y,3K3f)t#od<_0&J'Z@]3VVOM[uWuRR].n*Hpa&Dr-]["%[Y,dl5r9M6Go+)i@3NlW;Hk[#k>h"j)g#elUG:@KQIE'=9R0eqHFG1Kmh]ek.H^!B3gHa7<$`K.?/7PSHOkW`UBC3*^G.0UmbQ&X+9/[^g6AV%7.UKJ^0)\3^TkT]8q>g=C=cr$-5a\*P)[:FmlZpJ7%D6C7n2ijNN3pb/9g!q4Q8cGXF&J42fQAF1XF^lQ@pTkNd@4mABYa3<$rO6n*_JA`5@&0;/'c*Y?;EWf*W;Klj0ZNoT0]4?Y"/bs52/UB)\i8(((B%$?iOlT.?;Vh,=!]-!HK<=&*)EGL5,f*Wh#S8\>)OamYl'OSmgl=4(#)(dnb'Kn-Dqs26-/IN=5#;OqipM(q*hT@[)fleR1`8[[Qu?eRP_+iC)*2(ga+GXp_8D_]qIRSonq6=u?"/GSUE<~> +Gatmu']&X:ZtlOp),V%>.#J)NTH9mG"DQmk(JP^Q7+jnAXZedcn>ntlpBBaP*Y,HfNMeZHO0P42nGcm\1U1?+uEhN_b/q=5!IL:9tAs.k8Zu("0R]HFg-@Sf+6X;ih.iXJ6a6bapuu!uhP`QTHE3PJQ`TjGgu`8'.dBi#i7Qc&ZPjfR_F=E>#mtds_N=\)5+u@`K'bBE%#]T:>qrDMWlV^6g&0#6o]'#7!DB%5URB&FmZpbQo?RJViJuO!?fulBA0+2CaO$&b2%US!?tN32b&T,.[H,28"0:oJ.L__6B*X+6oj%Ih\HIVS=*ldc6P-lN1ONlL"dVAqHQd5WQTs0fpo$.Zipk',qHh/!g0/f,aEi10Uidq[fn@q9CF>,;E]55_O&0YK\MmX>&Fq5<=.0e3E+i[Uok$\;mAlbQ:g`aL$(Rn$Y]jN.O`A=!b?XI)7:=+HsLrJ:EEuU,sPjN>`,ub4p&F-8pa]W#c=@qP'5ncLP:.*mpNTlts5AKGC'[8BRGYG=5$%0Sp2N2F4.!'u]uK:T&9+Y7&H6SrJrnhHo&6BT8V].Ed$.K5W?BA@gb7a#?Alo<2d4i`&GA]*d>WAi0L\+qt71&g9-%8V58_%8eVbTL-@HLo'/]26CW>g@lZBD0k>^n$#;CQVgO3KUAH"(26]F0c^t[f4?_3&!5[#95.>B(($)WLi$hTO_)_!1j$`+Om5V,caio-UoZ>LQH&,VVl,s5:_%fGCY+P`VYqg+<#TK:B7j9N7RQ!k(``bphGe[0U!5et]1Qk5L8`/+TX543!1jG-f6Cj01-UUWB+4G*7IF59ZR##+[l&@ucWaE./4>UfN;9lau#&d-7^L=PZ6\F'&'FjSf7$gNpU~> endstream endobj 86 0 obj @@ -499,10 +499,10 @@ >> endobj 87 0 obj -<< /Length 1291 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1282 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm;gMZ%0&:O:Sn1arQL)3^R@V_Xne-d(,Rl9[uZu,o`VJT`Va\1$l/Gel_A]l'nFLIYjK#F5mkO_;-m/=4V8F6"'\qFR]uLD@m^a:_1X/6$aL4Lkt4a!Uqd?2XA5+lNGkhn&7jBA\@S7.bV2&=bg:bS_'@L=5,DJ`OOaMdL`9@:BWnX@K@SM]1I'/')foGI@P%Gu:tqGHb)MJ?kNPcGNlncp<_nhA#8TV>=ic+94_jAj>9eXEEo,HS*;t#-']+U6Xq8Csn1N0^+&L[b6ZAKjKHp@3;//_Os%pAF/n9UL@Hh3S?b<>">eE:B2Saf>SRVse@*L>Bl?o?1r_XMgoQGDU[YAW3@##GK'kYCTIR?>@0n?8A>u@V%9[DDgDhckO)Ru2V/3_DI6!uK\-[^H5B*Cm\GY5Sfh9,`:]A77MJ?//OlgdnGUQ3@4H_[bYW-N3d&.(h@[=p+_$4_)mKmeiI4pk&+;b#_^TD^F#/4fZPYXcE;Ea(enDA[C[_Nnm`[KsiZQJcd)f[GOAD-U`[#DmYKbK(&nSfN/';b>jTu1"ELF"Cr2L`%8l/?e?A86/DNnB@:Y2mUlOAO)Xc+4iZ>T_-mI!Kb:;KbAg)t&C&Rh''![X]e;jQhFrbe2Yp>$oaE0eENJ[`juCZnp'$p@BfrQ\9@qcl):S1uV-D/GM>8KYOOH%Qd==0K2A:&D;O8XQ31N(VOZ_"oBbqtj4pc:uEp6^hH&P"QN0hkgI*XRN@&H=BR\[h7E]r)("RArGSQ+hEP\T +Gatm;D/\/e&H;*)_2f';1F+8=e?B+DS%8$MXY9D=@Ij[O(@;B-,Yt.uVWa'o.9Yf\URH!>K#Bj9GPCUp\`784*=gUL_=,q3PuF8dIJ@W0qRL4aKAF+StQI+Xc6Cl]ZJ[gbcXVdQWEn\W`gLP_"pB8(\oG(LAjTaT2/_s'Sj@pW'B48h1&Gl96C^a\#[:3n%m^7f^"88(BeVC\=?QF[1lMX#1ZeX:Bg7pPmD$($E_hXFd_4<5>E350-X.2?Wh'JWNiF$$JPT\iR+XM*dS+bD%)o]<+_7i(_hp1OFXTC"%g;VW=o?8bpjl;XYS1E(>ZWU`rrGg^\X0]iQ0)Z$GAFW\CV];c;RqHP&E!Q@5e(^?.$j?^>1oL3!@U%A$/a/@pPl3dp^Re6GCZL=j&/!+VQZT<8rX?Ds8`km#C7ND:/2Kd&#/QPR&?$_VQ/f:?^'J>s]U\Jj1M(k-f5]"&LC.5ki957N:-2,\/.t5MA3N@QbpOlq5cEP6iQ_,#;)`s.7,Y9k5BK3&j3#=l7Ps>kNuiA?-3Of,lQF68J_n))2.4=%^,AArX3?0=-6OW@%`6kM+<$Al#')H^aXQ2U_m"fq<"=Qi5k*1,QDQKLW??+XE'QS'QQe(ne$nV#)'-L.-9)8@fI/p)s6!BC$CLGT$gs1ERgM>n:A9I/1,/Z&&n;"7UFU20Y&2JVEG'7?``?^^nWrbc=doV9mcO@f\so%Sr2<1:l\DhIl\c;L%P7L=;3$8Mfe;S[UN%k-AC6pW1l2*K$;Ei\O-f/E&!YL\)G\*GG%(Zce_fpJG,!?%LJs[D-Sd?kF>7:HPUE+s8/PrjUKEj/AP$P0a'H:E3"s=lM'IbjXDqL63)U.(=m7qS(TRQ^:C5q9jb0t'K4Rjd#aAbO,+=FhkjW0+,0HdUoP0bZ?A>MYIFTRA*.kdo^H;&+Y1=O@sUOd"i#&6S8L":GMADL)ILN]Q^KD,P^a%GR~> endstream endobj 88 0 obj @@ -514,10 +514,10 @@ >> endobj 89 0 obj -<< /Length 1808 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1696 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb"/(95iiK&AJ$C#ekB_XL3@I^(ff!ejYJ'8.k;sRN?!rZAD2L6W(,E?XHEkbb7]k:)iPn-l,sQP_Sef2]mgMO3>Y+bK85O[FX@+Vod`!*@m!knUD+Y^Ls74fR_#'[@7"Oq=s7,5:f.Eou*&*0l]6'8,RE[f1B/nd'FrEYa1RIqn%W\..I5URX*^emq/opjkt\G9\)/R+4g#GnKP\_#K%b[%#IF@&6\VLHR\r^Ada?b^e?ifN(T[n\U-g?j10q0n[=q9lZNrr)g!S7J%[.5.h^-;gDNDF)dH%(!gcHe-p=h7Y6=?9\!hSd5hd?N;:#FUFfTE[l9.)aRF'Gh'QqNYsDndJs@nP6qe-7MNj-OIgGdF'EK!A3\1h0Ml5C@>1JU(Y>?'?E5((_p2nCn$_em_hmQ5jbRbXX#Df4((C%eBi"%;A2uL_;&_<%GK90MIjANmeVk@DE,,*i#"W>rS#7T]d*h4_*3q.X1sW"e(#0<V-'RtX+ZHU(62"e%T(PAgB,h1d$6DoCPb=uVjC_f_@3a>_9]$f-<7GVK&1!+n)$Q!]HAu3CqZSQ59_B8>7'U9k7E`9WNo6M(emV72KVRXH&;AqpehEWtG8\[h:6kECAT],+(HI9I8n;lnLa8P`0`2L\'A"bE5AM[H,V[XBe?j99`4ZP?F3\dl@a&G*NREC>,M=LW9p][7tZO(2;'pXT!s7/20`Il5BXCp1GD1<)Tn0>cI#sjg(^CWDng+HHma5F('/REqEms&8$7'*FEj=:/o"$CL&P_f*rtq#7jh1gEWUq=@''R^e=)u9a0$QXG@/4G;QtC,71NU`0FN:#]*D5>'`i[r]R1@O=q[km\r]5XP@ra]\'R.UgMc>uJrIGh3mc+NX2kb_W$&fgb+<3unDia`'k2T)qCm($im@cfqJ<0qd--]>QF3Za4(Bko102l<$oIP/581QEH^N3B72)/B3iC0'+1fn.>)1k,o"A2^nU+hDG=k2"KKj.$=E=TA`6,Vg?'*\8i'%/5oQ:*X>!h,Ge?ll^SfrDqiS1-O\b@-Er9=drDD/a9^D$Q_6Nl1\o/n_"LF?^(cpBAisb0V/?U($CapopI1Z\ZhMHnKX6oP?.6D^$g\'^L'n=l5feMW`cC`.>#Q&tJWL5M&L%mL2kj^,M\gHOs;>3ANrNsr9GFdBH_u=G)30qGT>=:2nMf?'^cN?7cH^!pI[AqIDJ]Fp74E_]+n_t[Eh_W-rSk#K>"N#T]\CN%=4YXP*FL=B(FGLM6KcGAu'?O+DdDl7n>rR5*"lJt^c/[#75Ul.mg'2"t.0lF3)N7NF!7`qmLWKE'Wd?m.~> +Gb"/'>Ar7S'Roe[&G"6RLfI;r"%.XISVIX!\qpp.sg:4(+q5KH/dg`-c.4*5jc;-Ml6hYfl$f+l?m0e"`WWS91U4.X*P`#%t"F"aX[Xi53g%1:PY%NPL3'Z8_:=FH+o?+/QD%Od(YS93dVta!!me>g%2[l@7]M`FM&T!X)ru;KKB_h?W'4ZY&bt\"_=.@3!PbfE5ZCJc/1L@jVMsP/d`[7M1Ku0Aab0\\P\$4J4um%/QXk[A,c*#WCt9k+M?;RRYMAqb0h7pD]a,`/>ph0p752oK.F%A\V-XhL#-s+bjVu/u!_JQVOqIjU,o-3`,CE38a>\BU,su&!p,/,rGgC7*Q+eVC^:=0"=\WS+g7pR]ni5K"F2Q:nZ4bk`h.Xg.@Xbh(l@O.$_9FmW'jr04[R"i`:0?K5gtcL1s#YLgm5r>:uVaTp\G?3.\L'L_"/^7SCG+%]B`WSO1(]6FX?0*WUM;AfuH2Kn6p:),3'"b$Z:KT^j@?Gh/W(%6`G-(-T\BnS&39#H#'Cb6q8Lo0s!;VHeHIrKELPm\#0bngl'?$P";UDqKc]RP3?Vn&GKg+M/&G/ddrDqjJiC76R)&&#gG69A^f!L1j,]]6FmW#8V.lFA[6[#&@G[H"2b5%^0laqa]"FSq2EOpD@BY#d8`G;ED&rJ-?G[co-GNE$V.g!9>fWVs'%3&K/>\$V-j@if8WOB>NWc_3?'aLsu'*es,Fer0d!>3%;(anRV8/MbOrX@t#,gSn`;l*l=M>7WkPHb),0NeI*?u@dG'Za;jNBQ&7#kt6-Hr62.Kt\AF>#Ki[7Y/[&pe>T8e7N]boLu]2lu7HR8%9K]fXgh5pCB[eD1DQ<.,V8BWnPoMGCs"pSGuH(\UG[Mg4'Fj!"*eg^9)i/K]t)K+dijT8b`A@Jo1%CaaH6K'G)&NIg6ZdU4?l$iXKYRp&9h%i"Zt12LFJkM?cn"'6O!\am>]P\)d$Q$Z7X;KF"'4]:o#L,dELHH3bD@lr*+f.U.7(qm,3Tg!.gL:06C8qe"mPudBSJ'p`:CX9G>/`_&?Lqj:o/sE#+?9[\N;C*@GR7"X"S"o"'FPtpa;,Q9)?JI>[jn@VCHS:3-0?83J?6m[,ObgIgSC,/XATL15!^^N$&%!hO'WZ.r_$YY0li>ukmQ[946=bn$)P6/abPDM,j/E0O$5Koc)QJWq65COlBKFFej.+No_R3k-5Oi!34<(i;c5o2gP-gE-MX4I[\o?MG>ad-ACD:>khNq9RcmIu8Z.tAtRpgVu*%/%eTV&uW-Vi#^ht(:QNjLRfHom@7O`-GKH5Z:(`lRDkkLd$Yq#R#D#D##G"&%\ZjJ%[d8%L]7Z#Xlip!YY2b1ul>bPj^iV/V7ruE1#Wg!2elOahes4"1B^`))NGAPP=g!G>rW.n'q4%~> endstream endobj 90 0 obj @@ -529,10 +529,10 @@ >> endobj 91 0 obj -<< /Length 1637 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1680 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -GatU4gMZ%0&:O:SkcG0V0V[t:Jh2)/HBCX"UlDu>FUQP/jUft]d3VQe^8,;-6\Vnr(-uc#,%o10cWmD%bLo\7g%,VV)ufk[(>Hp=Jfs!DShGP"po]T=hmI36X_5Do^7=!:KKaFlo#l`*@>@'MAi%'VAb/-&@65*+I0TqaB.XMWO0cGRV6q[c^mr0CnJhi`Zh@^FS'S41G3rQJ\RV>`:d6(gfr%(Qol&jZ7]jfLF.7lg\o%rU6KY-q8QWfmXI@>ChO%N9\)_ij$/D@U*J>h=4OOTlB`aZ8.6:##qEU'3R81Q]*9$ttT)o>dWTaek\l5Piqoq9_*H>P6SCYtPi^7@15GcTX+hAmu,jE]YUA%Vr^W[DD"En+l&E_c-D7?$j!Ga?(Vo?t<98B+$P_[Eqm/(46Y/G3#GF`r+R@13V;+%n=\;310ja^"f1&UWfrcX8\Z`r\Do[uOeJl^0n@,UPclfr/KVG_;`ZDFNLAGp&>1c8lLHL/.[KR6MYqobrOUJh4W9JBDq[=gs7H.;#E]:4"k_4f3gbCbMW`kJLo'sF4*=jZ^A?)p]X>K$rS2HCqnA*L&kmH8^JB,;*^o6/65*cmj]]=J[$[]j&rQ\fWlQJCESF)mEVT5aiFY"\%L6"f!e*s$$T0k_U(Iu)6>eB8A%kGHm$\R(8bF1u_[m[b[R'$cZ"=M2;4<42Gn&N&lM6Hb'@/V`a+`$$?5-as!YIuHh[6U9RZKnaPKG;RtGkZ6T[)INsc6e^'PX"^'>YmnB`XX9K%a*#Y+dU=oaBMu5FR\+a\H"G0f2^]bbf.U3n(c>4d6kkU7d[HhhX)A_FuXC`EN[jc?C:i[pH(OIESsFfBlTREC+dGW7*c#cnpRkV=IH0MV+Q6D#)Pdn+020Y"W$f@S$RdUJ;*j#:PjZ0f:)29OL",C5O\qHC7e:f[Ch\7Ip@q(W8IF2)QR!;7\GhEQe;>0[@?UoNA]s=nhi@/U#(?NuP@Lkod*q]WgW;<_'m)J`qrclD*6I1F*VgKT*JT!ui/3*NJ^8\PZ2=I78X<'k0Gr\'S,KI4p3SIQ[@0!slNutF(h +GatU4>Ar7S'Roe[&Gi[:8/U/9^sJcljs!.sCl?o3\du/93Q*2jTr9sHpEM!-3g<2`h%1hi.IgY,Icm"mX2V9C`T+gV[ds19,'/n4`,R@.L6;=](&8/nUVPj,fe!,-I!YHNOC]gEY?rq-a7JDV]e=(gd'R%@curU/mfdFi[NWVs,M;X:6`0=B@.4qG"QcG*!E'k]Z6hHhi$iQZiNBR;gi<$U$`I&HAG(ZJh-'\7pHQ_q3;S^-S@#D$W-A:Dbs7]8HR\MUnLH#^'th^Ya2&NATfNI`;IG7YM*QSp>13iM2gBkk>lNilgf*`N3JWNE$Ha9neZ==6$;uLL+l&$<)^0DnLm+A!imORu[OK;h%B0IgK,pch8rm?n?JdXelOQ]Ff#i'F^::cN!1833Q1.h#FZEBtKR@B;,N]MS)aX64Y/(&85BI.=:%fn$'PkJDB6E3o4HZWI@KsFP.[arc&d#ok%A1p]Nr:O=$@K0"+#$W;p5H481^eAgkn5k(Ib_.]NM]p5T`,0nEB"!%!Gdqlo>m?qD>0Rt@,luEFVmg(1^UF#rd)VRX]^\Qc`Ut/V]ZVCRPrMC/S]I14VP)HSl)52C?K+Y5n[%oJMn9DVb%%Xd**!2fgMAOk(;`d9OZid-m0eCH!/M",b-\Of\6tB-cBW`s1q,>0!82+GRt6'"&&UXNA1DGA:X]`)%$9#jGC21265!$1Isd,R"NZkIE?JH[o$#dL?7?4.i=&<)ktqVeNaT#<2>3fZ;ABo$`K4p&WVPKm+;EnoO'.H"cY$1D2Xr,a"SK,=c#1@!,KgZF&lf.)-\/Fj4eijkQ#=X,V;CoO/'/`\4jmt0Y,/Xlh2=B5D=oEX(4EWQZ9WpaD*X*Cf')17b;?S_I_*jC&IgT1-m/g!B2O%rG3Z?F$G[AIC:eli<:X-WAu^o?:!R\FIP>`iKph9*=D1KZ_67h'U@SP>2)=IV-`6cNM#/?*pUb:)j;NF5O?4)2ea4,f:\QYd2rKU?rKlsXak'2C8S&kC_M>:aCXU9qAGg_%2X'tHPP"-+9G3R9YqK=a/glXmFeu4#oDNZA]SL9s:JY0(Wdf[2I`fbiM%5[5,!StV>)n1!c-;8Z$Bleu=btMe@.bUdX6]@Di4%kZOY1^=b^:$##@%t:/<65WPR&7jrlfO=>ZQcSY"@>'acF)Kjh#CmXU[p3=9/!iofXhE*cnQlPY endstream endobj 92 0 obj @@ -544,10 +544,10 @@ >> endobj 93 0 obj -<< /Length 2091 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1873 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!#]?#SIU'Rf_Zd+]0a;+,i55R+;3/lJKt[i4#=]E,B-gVdXMV;sVhY9,&nk+tK":=Br3O]\EubBj`f4hR"c:IjlNUX(/q/]HWE;<$5g'o&FWmg&OYFl<(=*-`5HepR,Ukk40@NYhb6^DR7lElB]\`Q2a_3T>[mG%BObU#TA+[Ir_%Pjn@5PL#TH[G0?F+@X6u.:ibH6oGn.#Uc&,Qp8].>,7\HOqp^DQa(YE(,f`"Z!GZ^[kFkuXQbM3CEBe[cF(,4I7s,<"'_Q6ma;/_2eUZ5[]1'&4Z.ajA;7>s_9%uWl'!^rmL"6Q_7ZN,2TP_fG'4qa\6?T&U0'+N5/n,'"8H4,,1iLoc/#qYOPql2?V^.2HF'mc4t`2`WVgG$"n*/fYAZek%Gt]+n%+7^Fr-EeRng))),HnPRlu)7+i,@&Tgc>#dB^"HeqEj3s,qSSuQW3E/U[>"4h@Co=4Dfe+fihM&OEjX[IB?77Z8"^l=ZE:%@p,*8uP-9qGr2_^Oq+oOmX3iO!<,$#eE&57'T[e4/4']BQ^LNAuTrJ,(8#I+Aomg]o>_,!)/R;'"NBSkn4h!L=;<[ao!p]hZ&PiOt>;00ItY>F4Vi-Wb`Yi'?R]6stAO(4To6b+"dD[d#Lbhki7g^h_DOqdpLOnp*MNrk`]?]/@acMf8LQFAPEuS+Bgl0%Jn:u/8**`ZIDX[4:.A%BX;=FDg?^3<'D?5cXm>j34j4hiR-*H8SGMD!Lo9$i[%\'VLR#/[U][:G?[W`\7[-1$,fd<(!/$[pWY4F'Sf^ZIU4V[#]/jGn@F!JP^W"`HX_6.j^.ol+$-9sP:+lg,L(j4r"gCG4f;NW$^jm@.at3s[!`7L*0HcV(g9CYl=H,.WP.]6&MEnS3ZD,4C0Im>7i"$#[*eFE4\i;/39*S%G6f4#9a\W'H]I*SO7`.IsMNWG!"=&0j<%5lX77BmskF=);U%3FP(TJ4Q9VdGidPW3*j<)U=iIOopJ.E!N;@'&fOSTT5<-Um:SdVF=qT-qjKq[@q)%%F`;nbsS9Va"b&#%p5_WAB?"c`QAJ8nDlqe\q4?r'%?8lK_qM*"C2W&U1ap\IdEXnoDm_pEddiPAY[[b.CY.&[F2fQYu1!`h6Li+2(6,RKH/IYjhc901IZ^qfF!q_iH\dl[UStTA6q2lH!Mi[X1hPT+ngrPh>[)a-FZ\t>*BAIHOdkp".3P0)l-@n,lY/UqB1`%&7&2UJ/Tb*lWmd4?rId&Ce(-RSohKSDB-0/ZruPfTGDk*Q9VSF'ob*YI,M^O%,/=!otdg-O(45-0DA0K9:?Fm0'H\m`DgThpS4p[iRn'T5$fX52C+..k;@H8c;M4Z`$ctf@+MX2Sq>mo/PLTYEhF]W,7;:dDug;f=3:F^9$E;\J*XnY_VZ!DG]A"FL[IakJXjiB^bKp0@e20W&l+k:a/UsG[ZS`^eVb^ML>LI[C4qrbnI"ugkZR"!h*Rj+O_G=1bmAW,(+ZfV7*eT4tYq@o9^I\6]gf$u8kHD)?=#TM8$UF-$eug4.P5ZI/~> +Gau`U>Ar7S'Roe[d+]2W;08.1Zn'^N));=^L)Sga]E,<+fu.FLV5UoWY9,2rk+P2sDS*"V@Yb`?F2!^u7dA6-o#"r-@H'@anc.W[m^\pQ,`2;U@ekBbLRoGF$otB109\>e4T+n*G5OV<=d0T'S`P\mhs"amJX^nHZe.=R?bQIIn(qV<]68(DG-.g7S*s>:j\%Vl!Bm.A!Kf7s9\$c8)_h9SAp`mIDu;Dd?QQ"%>LE8%ZhS7-B^!&?<4&37dhJt8GJ9jJ*CCodQgOEl_@_.;W]uhOK9a/NO8e]rH#;'NpY9.A>I1_N,6Z15e&UgcU05l`pNe7FtlM01LLalHUO1Oe/ub+"182=,[c'GmhR!;T2g6bSX4eapQ'`TfQ6#l<+Ate1\$##2*((!\N=G$-R-#&EP7*6p-UKpL>n&Q]Mo6g\lmR>>g:d:_FV,\JO+Z/i7[.qmdUOkd:WLG[a#@V40'86KeJ2(sK1&nnSiHr6?#/$l6F;b.UM>9M$J-4o6qnr8?*)Zmed.4fO56#D6Frp6Z!HX_RJc$e\-]8Ua"2c[itLn9[^^^OCJ)OI;Q.$B4s(#jRnLm=8Z^q!t=$.Gb0,"mK"Sen[H2PsZ-,=Y[K^TjhXV4to0k,2TrYU2mm8!e/mW:0[Z;k`(^,OQgTnH3MrMdh"X?Hfo-5o6J/ROR5=q+RL!V89TQ0JX3u2/r"pE/'Zb)L70*U-.PVS2JAqs/IHEKP-\)2L_3J,dP&qb,XU4WAk[PeJ?:/R9$GMA$]XNrJ*0De2.sco^jJlP-SrE0dUF`C/.2K2Fc-9:K9BbK-#_1Ag4E$RkY`m>m[D2qXr(?hr#K-:n$PVdnCR4,(,Qt>$@salnARK-f-%'lX$Nac=q9s)L0:D_dkGXd:%(Ke#%^tKIk?5[&W=r99+/(k:jXP6.27f(FF+[$l$[0%$[02kKl1G!T&$M,+n98bkog)_=mC,iG7"j*\9.0RZ"[c7N[382P!=W0tptDl4kU4\L;!i\asWt=s;i<@"tm-"rnGFmnh$#8a,Aj7b8-`=BRQ;_-L,=gIepVf@d0U!Dde';,R1L<_fB(OL4Z01ZVUO"?"VNoPAe^W,9T5K/p/`=db\6Qo>9"oh$^jED^ElcYGR!Br>^>bP`UFK0f;?uH2b>QGF(B2:X"0jQG2tcN;^(Q1k9:/KYcZlf#)g4CgFCR7\jFu-&dZpJP%F<8d'!oIPD7XAMjh-ffUs$7/6hg61GJG7R$#`R?HOtU66LM$c0Jh&%D7u-Ft;]*RP$V_cIFis_o$BHY`IiVIt]aL?u)p'`M)Af@YNIESM\G1N>jddH,lH[j(E3:7N*"fmM7VghD!e&REqJ;rgg.R#]*OXd2jB%R`0>,e/j26WgEGCBmB:#q(m,At,Sk&3"4fJ:GX`\&-Fr_1lEk)$\j3E65MSZ205E=QF&j*Ej_"YIKhU:49_s:%//a5qA\-uhR[0"ZI<9mq\>m!pT[boPsmgmgXla`c".GDBH(JLkZeS&OGTIoGAp8%+P"EXSCeH_St~> endstream endobj 94 0 obj @@ -559,10 +559,10 @@ >> endobj 95 0 obj -<< /Length 1690 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1913 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm<>Ar7S'Roe[d+a`"AjfeOV&3Aec!7%mL28U<;YPa..%>`<3g:=+q=UL.b@V"_?mhjt'#PNNV.an@])ri:3icENl?9k1RgmWEf+OSW8kX-uaTI^2^kobh)40R<\*V(MG=kL/l67E0crDcC!C;Mism%J.g;tGdZ\QYYIVbDcfl%kgK:cbeG3u4iPM2e\77,Br:.(BXM2P%Qflra'nMm>`!UTCB>!7rQh2j.O.aU,4AoSG_;!8M8bHFAs,Cq@7E9WE3>XON"J2j'#so=HfQ;49-Je2Nf.,bN-QdVGi?.IfoV]"TIC7YBHSF))gS&?09M>R?/28)pJ5SH(3p[f^a"(ZV7p28AO)FO;$P\*!jL(&oY1$Bn2];0\Nj>5V`QB:.k0,[,3[*[(*"IFF\j772RG-*LNUPK91+!%?8o9-;7"AIt#kPu-]]U:3[=67XYNlE/pjD8HSQB`Qj=h6=ru"758YpQf.?J3OJ?IF*;b+EH-K->/H?T[jF2KJrC8\Ei7D`aB;b$@&oUeLlPg[k&+%Asr1dp9t1#@h!9kpm=gF"L`"10LYRB,FUeXncg+cL=QSkk(h4@uumAk%W3NO:W]9=fC;Be.jC#HO1t/V^CUm=`>F;&m,FVtp$@DSCrH7uefqNrAJ902=ITnC/tYf?Z9QVs%kOOK2OJW$lP=)S1b[5o=s>M*j[]&-!>a6Z`5nofdFd'BP&`MQRCi4?#[\%sq.TqfG7?"NOFT'&8NbfYg/P"/mbdeZ?PEM*gjMYgc/r>3XFi,ms\=8aFcmcHDLk!5IZuodgT$\ji,0-D]\C7ASNVA`)<8r8UkJ:Am.dr%9/4BBX@m>:L8J1:,4IBjP!M[4GSG'j'jRd*Sd2$DS>f&5@L%kWtXCBs[W(CX]W,-<9A<@n"7`J8iiDJ\>+BH?\$)>M%#R@"$@%p\^l^o@;'+,32,,qlY^eLcD(88aOD:hqtocD68h,LuL,XS;V<._?t^,U9/;P#\uO#?uFV1U:AXg[@(cQHE0jOaZ`U&b=A!dc2']Ea'o]@6:tc9p/)ODI2-)Qr,;Z.`blUW.U@=n:V\e%'8#4o30CBqYdaOCZ$hpc[;LC.7]l>HJqoWS]"tW)O'fL&Y[4rU(Kn0#^FXIg1Jnr;4V[6G=e6.^Q?NYdXCUmaV'&M4$T`BKh>~> +Gatm=>Ar7S'Roe[d+]Nk;++"*AQW08Vq/bDSSCPT8F67\I\+J?[G#8"0MgXTbZ)9OQL=L?:Q%g=c'lo)?$jn6^B)ti_WXdAY*fqTI/C954gXuB,HA5*Ed@Up%dJRE/WGV3#JY*;PcSb*aMGdi*c'@A$u1kKpnZ$n2SQ?!9J+1L#P!ko!_)omt!:[>+]rUt;5_kQ!CKEYX8J=&?m;M?fM<")jA,l,o:JTg*L2lKJLB][W28n[EZ%E+elYq"=UXYQNm*UmM&5_SF272cF)ORAPT3`"!>W!b\aa/1e_/-O^Z;B>Q+n3$jqj&hji8-SMgNV6ODB4:l1VJHYi7HGKTK(#DEW4H_=gWpYhd';"24R@2+8H#i0S&5u4DSUad9G$qP&!`<'!dpl<-(J1*5+jp8uC\?(-oEsIRIq9:$IYk;^3_KKrtOGbI%j"dQ-PA"6`7jCKd;=T1!IPZ3i"ekTM@Of><.*Q%NO$$$`):,M5o3=C'H,J=qV<2jP79lF_-YI)Mo_H$\*"Q6_I*k-mkV"F+0a"u@K>S1N*c,7Y+V(WL+TM^NFL(KKU_;AF:%hPkXEXt>=Mk9(g'%:uefaqCf;)`0ot)A>HUb_,\jfeA7n_2Ai/]BEep\Nhon>uMekmEc70DdYgpF6n7c=b>AM]3M+@6;,4l_7_;[OA]VL2$bj4H#q<-As4VZJ87aVbqsDa6$XQL9cJW%IK=3KEDdC'LRP9'a.'+_pjdCMKu%]KF#Xh=XXHQoSP5%D%^PSHKs*,J[G(Vg(JSLr?r!<_0*tPbkcL%bK2nY]B8ocb;mN3?c(K0OUS),Srs*PfVZ)hWMI1Pm:WV]>+hBUh!S&m(ssaHe$,e"IFWl1%RQl:.o9p?rW3il<2HJ"8hA]4lqh,a8T$)0!F#:RnT=*>.>-;\U;uAbho6.;OG-l4&8MBA^!m4R=NI5Im$GBTX=&\t@Q_be;ECDLbG"_XC%sDS#iKSea3g~> endstream endobj 96 0 obj @@ -574,10 +574,10 @@ >> endobj 97 0 obj -<< /Length 1852 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1937 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm<>Ar7S'Roe[cs'ZrAjfPHAISj>>MQ&WP:Z7P!R!1<2J!8X79>^pl)u0T9B)Whg)a')WHBKWn2n+?L\s+P>u!oI7bCkD^JCWG7BY\J^A?_seao0U&:'3q"a=RR5=Q_*:7qVb5C3+XKK6Pg2,-PX4j-k*Yd9h@#kD9IRBE*qh[tP!4(D0hGo,WO+O%b;s%1D_'ef?="9\:k9_2i8[>aZcXed:shrZ+9j"sgnJ>t0L68"/'<"&`d9L&95;iJ@)q*gTT=!RCVa*QR^p\N-Zr3I1(dD,3r_2He6>(@^(lUf7*L&@C*X%)OX!:1oX!pHb(XEFO4[H'TekKEbp4!2nm_?d],c5fB4k*,+pduuldpZ:K.JJU'Vq4LbQ5[g_$)`O_#Ji]jIo6$W5!aEXZISW2RPX]qujXc^oQ:.I>T3(9)V8X/4.p!j-'"*)qF?K4J;?PiVW2NY)Tf]*Bb!joZRnZi*,,^9\RY3-F=]VMj&l`]Y2d/gV2Tui7X`UAFm(e)FFdn`0&cOXcckMHb=:R8c\%h^,-5il&W6d(poYgE&rRRN`.D_$SJM@GEbkHo*7cnb*AiKG#`%5rE7bj/R,LNn0:l)KCJ=\\WMN^]O2Mi)*=2cQ*h\DR]!UCW&9VW@31DMh8]nbHX8Z?_gpKR^8:7V^mRk2>Nr?^!8MqU2%JA90FD"<]d%>@T]"Gl`WE(bQQt:j8scT`.#a.<9iA\BG!Ou#IemeE9r]PD$bQEslrDNPLoKB[?_4Je:%6C6d!%'>\.AVsQrrH7s9:D9rspiVcY&2*(]Nc3)UjSCoB__J%&-E>gPO4?f+S6#'=n>iqWesgIl3U@N@5SWHE6:j57G*cd5Rp":U00HJdi8:XQjaUY;MD:"_I3HY*"T9l:6&@$4A-U't](N]p^_KqM(\d:W]B+-`Dn\C='D;3<)'VJckD?@aYCeAhTMDLXKK7)2`1OA0&dKHq6;\l!UJPiiEi/^jsJX6!DhWEFkWrFN7djD"T\taEG\BqOf0(BZ/4V:+9$#X29oD0[mHrlR\/.i3NZgunu/hlS"0bH3n*;ml]bUS^OjaZK`17I?*Xnugsm2fBQA1gj^S)T_r]_Qe]ftV'(,/B3R9u2$1_nmVG(WIhgPsq58@khK1OmsPU3$'F>5;>_f[j\:8iuN?aG;-=%o?c$/MOHW:d.*7tFI/Xkg%_+a*%r]pU_UWI@_%$5j7Wh0.B8A%,(8L4!8p=@Knp9>,Q]F6'#KBHZ3P962g-!/n+oiuPPnOMGAaMA&q1N0.&_H]`e1fHK!3WBaH]aQ=bm(q01T@h2\-b>"drm[M4/#tb!gu\f4R)!2H1!mBSj`h~> +Gatm<>Ar7S'Roe[cs)[LAjoSHV(Dm.>MNfR\umpELSbTh:"]Y[d1rK_qWgYnP',uM[TH/H9fT*P9#7UaVm.a)6>Iq5$ccGpEl1X4rI7p-;M)'m%',!E$H@Qb.]6E:*B0]c]2ah"S)/ukWG,R^hn.2VYH,;chQJ.iXh#d@c`NYism;Abl1;4K!W!(YR\`P:#Z%=u`Me7>*P:35hk.F7+.-rtjc97?mWaik*H:QaOenbKVl!!IMZ97j^N:i)`pjk\H[)`a>uPk=$'TF(kkTljuNio7k9n*d=ZTEua\L0&2*Ht>plKjYW#J3=1U1-ZRArR>[B]Q`q[j2D@GJ.ekSQAmF29uD(/_"2'K(WhV3i*W41I^^"!%>N'"o)m*G"rBTh3`UYNLdG-C'M(&Ki=7E:AlabCM7#-W(#'^*g:?Sg#H*iq-,18%=8D>^>au+5_CVC-uuo_L8fuO`+3s(Xq$SA63YBM#@Sk*:+f.&Ht(?0?XgJ`=LOU3_W?&6bFJV?nGTgl"Ln6pL$lc]BDG6BkC'"aA'9!Q$KUBj(%j?bgsfh$:r2-?:@"_=GQQL!]q:+(6eC"OEXX4s)3L!PYBS'oYJf1Bm*W6Ijf)etu=h(8Bc"en&U$g2scaWFkUVc]d\@WYk-^.nm_*J?F*Z*XoR,bh*2*n3r&IH>Y7mXRocK\UGr^?0%cGBR1Mps'^?CC=kZS+FaUfX$gjdlp7!IA7TXg9662BO=`VAGfrr$sorle$c-:SACh*:AaBtqqcn[]/o$OQ/1IUX&9W+_kBcnI9:9S"%27Jrh;(@DB2(BQk^r_Oga)U1V(\/u9ZlWE^*!!fs(6%U@"h!N*PBP,CJQD?9AU+=.7[o1"rWQelp4'rr+`1I1Y6H=WhRET)X[:)KMP[Z?0_YB]AI)mS<64hV^iK(=C-@>a%eRtG]mT@QYE:A.D=;7FG8i'U`;]FP5PI:^M5ehMaF5tP:XVmY*K,H&Uk*3/I5VK"ehCJf@1JCB<_qor\]`n+nG!/Cc\![=ee$5Pbs59^V[]Bq^b[h#oUQ__9'ZFTi&PfA>JB[MlQG7eY$HAImY"hrQpMnNF_"Y^a/qtNen+i!R1CRo..egcn5lfKmT#XFYEC(9%FUq:6hQ5T>r.]&/!qj[s$olgI[@YIf-lg0jL5u-27%fn)eH*lAi6XspgquG(J0P-OT\HMi_DkLL_#L$eDVqp8.272));$79E7P9C4VO)H+83#\.08?F]q5Q5to\AeAKH_>%,i0X7',p0GOh&:fHutP*cT^OF`$m=T'Vu&YOZFgBd7Y\s\E3*o4gmH.7Q1<;RXjGRrn7?VA_)X",Yn4U_3N+Na$=/$mqgsX,`"epmbBO6lq"fX)^X^,nseDuPra3!+V6Tckjg@!GSgUu*t=uJ#?[kAR-k?rpm;J[QB93"ta`s`k"kpmt["RaScM2eAT6~> endstream endobj 98 0 obj @@ -589,10 +589,10 @@ >> endobj 99 0 obj -<< /Length 1313 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1492 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!#[gMYb*&:O:SkV3*QQD?o?#)X,>VI!eqD6f#L0?mt"g6=2)Q<]QpjmSPI:`RW@';I4=^k%7^cC>ctS09P\ak(4sF$cD)qYWOF@>#ZYpXObSf>C7--lKgdLNQ5VOe+#iQqc1?]G<>smo>8AQZE\+N4oYiF@JD%f_A=,n)KPOrRlPXFt3UG5HS0idID1$4;;4o4.=C:l8OpfC:p1oC4B3_q4IR%?gFcWInqX$%IWaiZL406ZH\fROoWs>E=eO$*$"o%7c\XW>oTjCP[*3ADU(;Q6a;uX`i8e3gYkB$jW[2jhQcY/M4ER3Y[0@9Xjrm*7F^Pf;i&(e;JW0K8C<&`p%BAfj*\TP"$6VB^\G'Or+];X*e=i%8?n1KnL<^(5O/&%:RSQ5'+^kW_h?J0!*VkWj34@7rG+`"2Wgf#upc^gJ]34(LHs!H(C_tHV,l.#.C*[-/*#/QRV"$O^9]6Fj"V$+b_PR6Fu#-+0f$0Y!>(`NAU>D3\5)N+Zh2n\'3$ptoKbgbO^=A;&7GE6)&f&Urg\%-hU\o1AN(NQ3lP]JpDhUijbeM@^2dN6#DBq.)7Hhm%N4n'(+07nW^r6fDa*!lFJO:KSYQart6PCifcH+$DWYY#I/b4ep'<0J.MmLLpt`b##Y304>sPC.&\Z#H*#WR60\E++*]2Dp]WH+Bi0R&WY/2"DVI5a@Mi;ZQ594StS=/6^R5oCj:d6d"eB?s0Xijd+bYlpu^s,,WIr+1F$5%b*3jF7r'q`DZ5QDTsiSZV[F[5)Y,h^m9)V!F_'*`im.HAW:STRaFg@uMh:?H.hN)3[7#VD=kg4#7D$6&YRl?JGHM#i[2@)28u^2"2?0?o*OL5''%dAUlVGI`qJh7Cq@*,oM@nK2>$r6o"Cpe;hpG!84F7LHL^FE<0,&H'tck1O%T^>9hY3"d$:Q`=lT%PJ$nqSmh0s~> +Gb!#\?#SIU'Rf_Zi*ui,N(B*-(lA@];AC(\2G7;M^cW#t9\BVdd?S5iq=gXJBO8hjloc%"!llX1aa8:$\VHtE9L^*OUE:_4(@(L*'RSJ"5nL!pN7YhbSApq:*u+i?NrC#H3&r+W3!.[_#tKZK#Erub21n$a7o2:/#<;2iRV^>X(Y(:C0%$%Edp-E6Z(BuKoJ`6:hAbNsbk.R?6B!??^R0Q_@[e-I,tq)eM[c2$/P=Jc$Xid0#W6X?3b5sR"[ci%Cuo7ZG<%?0`F:(_WZ4K&(oA4Z64=F@3RUF.(I)[mZ]""CaFX"hr7EH^fqi2/:.O*;ZH$2Pa8?_"R!4F*6HaK$@n8,q9=6(eOdMNLa++X.M]^V#VkJ^!@2"$g%.Q6Q_515jO:7Y)M"C)`='HfU5Q)NM[d($e"&QeYclk/E!DFgJ]aC)cEBoC[=fDJW^p1>s3U(+LEV';uNlSnd>+C&6MP=(OI]"R'PNAgAq,L!4L/VbKh%]\qN\\n:r%.nqs/-K&,>aha\2_9!)mhu=W'as+V6l8YA!V>mi'sfKe;gPP5NIIE*c:N`ru!C7%f(PmZF4f5*g:#^SnAm[4Hg0PB:1CWk9FC5J?Y$W.e8%'71J-D:aW&U.F+TJ03oN9I#QaF_2dRDEY\jWbo.`(5=dY!t$@7co&78LP+od-gCD;3gr<GR\I+CLN+.O:YX)dmeWVBP!Xoa=WPhDjFa8KFL1XFHGgf4)-i2QR@_7W9e(VPT/.0WcrbD$*20Bg9\?HLBWZZoq!/mr'V0_6EUd1`G6tBT#b&HSGc/#6"e@`G/3~> endstream endobj 100 0 obj @@ -604,10 +604,10 @@ >> endobj 101 0 obj -<< /Length 1805 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1696 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gau0D>Ar7S'Roe[&G!+0M]%?aFX`%H903q-MDe\Om@ics,#bp(=`ee+ls`2.Ua2GmaHW0f(kUBe7@s+A.mNPg%M/6X*^@06@O/_#8k'A:`Y#TN.C%C$>p7!"kcmBf9IPYK"6fjMW3jIFF[et1t`t$X#7Yu&1epM=_])7qm'sFYgCJ%f6Qdb274o"9f];!$j@l8WskN."jnh4(qB5@M4:q5g&mi_O\W-S'Y][$$Q4fj"+PY!0]dqQ?/4o'NWi$:+Al^)fleIe$*n`Q=iD9_YGjcUB'Fecg/'JB+tS8&-W0@@i0[t.U'=+3__Up%f7Roe:O&T$">@j9BCQU>-h2f0p(nqWkV?GC,>DmZb1a]:&&H*dcYJVH]LW1J6.K!d'OqDmc"!^F)(64g^)oTWn])hH;dN)@,=.u_DEVG[VimpA,%0RoBp<8Q30,TM<`:.%V`tfMP8!83$j.'2AgN,6f"Re_#5?,@T8+V%$C]_RlV]S>j'/!=Kre#@r'&]sP[,KpN*0O3n&dN"4_UVpS9LB9o,a;f^bc+,ij@\[s"c9]fRYJGq5G?IpU-3?d`L9Y'f;$"ecf5XjL,irm8)7HKh12<$:@+ikO]b8R&1s-7\VnES)DU>b1UXp-863DiccNmih@cVc,`-NXHka3"kPrc6'DA85k@#Jk!;]2rDK7(KEpT]_8j-?3%D"UiW_`&3'I=7U8`ud\:dHM--_@F/RhN9M4:L_M^$e)"Vb7-[C)o)L8),-ZPJAQO#"t:-hcj11cWYL0'&ZI0@)l>4AB$`bY[uD4EQ_X;hu0YqB1_+C5_1K?:F@*tsFuP.XqfhNtg=[]?_8jNSRH0>>T-Rq;gm@=s-gm`&qUINu8`n($E6UM1qD=r^9sET]%Eh3@(-A5Fr1^V+@Aa,_dP5.S^Z]XB/m&'=Th/!3*KTfObnl4+S)+F7+e1detOo=mt0Q$Z=T/p10oeShI"$_-0XXG<[\Mimqd?H%EV*SZgZnDX.u#.^%K1cN*;o#VF)+;8;?KXW97n7RCd>0"TaG]T3@TMRtMT&C5PK).\4u2XQOJIU@"q96)tfN>qg(d^faI)D*jYbcKTm@4%@GV8&CpSHlk#H1+*,=4)2#62Oo3,<#ES>HV-g#@Z?r.6)=0phls\[RGsn,$TJ3rjgcG>\goJs'ed&m@$.&X(SEf<_>~> +Gau0DgMYb*&:O:S#^L+kfSiAWM]tU=ej512P"c(o1rVei.9h.bQ$9ko6KJ#*c`:E.&aD@r&M=af)mpNOUnm-bT-d!r[*ROAp_\]5M3cKh]-bEE_Y9o1ZS@X\4t,T`f.9VcJp1H@^TZj'd\,c"WLPe(,T33iE;VP`Nn2ePuqlJTHsZOBT\/%SusQAT]@W7SgmO58I=Ia(i#qR!b_R`R;`U"N:?/#(+VZD5YGA/T/Fkp$&,m1LkY5rK]Q("*l,Z6/!K,#F9oaB.>48QSBrg%:*;DBlm"99R`c+(SYKpA5J7e-B!Y.8#T*(9/P7YlrGA*Z,9H9"TGMfl>g`tlBm.e4q'D-A"glEF,tKEQOEh85UKS,0S%O>2=E)[O?F3!p51!t;$T,VFpu>lZfAaukj3?C3J_!GupoRlM*;H'I]@j5OlT*$.cjn95YV'+`.Nsg(EbNCf7b6+`U2!hs,m*PV^.-9BAj]*r<$"uJ\,64IG49aIfr+=(79+Q#mPMIP"*Wa_A_J>M08s.(Ebc8TUS/0X&+S7pVK6)[f/s3!go'Q'=,;2U&"%V1:[FUJBo*\)Cnqc4Pmm\37%%-'cQ%6u^_O'O:?:F0srFT@AIQ(]l=a\6t^o-b"#dYZgA9kA:9iL9--]iDLFJgX1CC@8F_H9uJ!DYoHbo6jes^'Qu`N',bQ>1!#QBmc$qiqc\#H%I`(?f;,?:)[ciq_?;i&ZCIM#)NGKEsD@Z0u29T$Z`XHo$1+l&#G;!To6b4>0YJtV(4Sa\PBi0r1k+M<7cQ6'o'];c5k!`knV6MX4lVbsEUWcEb#\qH1j:2[05d1&?[S.lP66>ANgjg(t^U,m"DjXl_C6u023lp)6kXU\[a3XnGQ\!*A>r4k6CU\ShT;KM89iTLL05)BaHU;WMn*J.$amn1!4b1G4bPQS&:;J#Cjr61XWZGlfrE>B30b&`1lr>+5hPc7(quu?80ng,E008@@2K/I+W^^3V/S2Dr!mcb*##0:9?K?m_WOD!&V7hEV&6%GR2K))c8*^8c=#>G[+_g3"7"s-(:.>&'Q*\d>cKS"8V76DLgLb$8=8O_>Hr"bC.QR*KoJ-Q/WPOd_%pAOB*@1;UMu@]m8N=8m;Ubf6_??.C3l.E`t.4]UXO("AV4n";<-ePanG?k@JW0+>JhO]"ZV#pJ`62Z:j=#J,\:cFoIj\/\I^)6,@2L4jTIH$]O3)/8L6f)8uk.jI#f0d952R5(X!/n,8ANd4%`3UKZD3X(R^i^(Ck2uF;rPWl7,2$eeW:^"R8E+$^,,XU^ endstream endobj 102 0 obj @@ -619,10 +619,10 @@ >> endobj 103 0 obj -<< /Length 1120 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1618 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gat%b99Z,/&:j6K'fsW>figri*kB7ZG\U-U<$"deR2gkl2H>90&GA)u52tO$Ma2Ga;]`"$^t?rj_d2U$-;V0:S>:Jq>+!s*`b-GEc"L:a8iCq.6o4hs)9n*)Uc#51_BpiiBNR*82,VYcBOkSjff^`E[,1fd#+]9'*[$Qd&O1qHGibUj:Qg2kS('[A'TtR&0_,UIMe1AT=!>'M$21=!k6K6HBO['9:0Zmk83\V73@p7[*`K`(/?XqX&S(?7H+2X>R\qdVM&:E:aFsTKjjp?'KIT5ooR@W=3Sk!JQ=@ij<4-EYka-rT>Y.ZDDC'Yn\@_e0)&"YME/Z!&k3DfuPQk)@l@r:L5QnDZXLd:[]D9Kh:,=,d`X5%!E/7f@qd,@#s[Q`Y(b/$e\W^T?ukC<"3lVQ^dPRs9\1XM#34?u@oe&0uqPGM!l%`ML[A^d^3I'e`SDuTe..U(9k\0:WWp`Z2^'n'S7K`/uVcI8["BLuJ1e%LFDifHIRD)BH*-VnTKchCTN5;d(cUVF5h#c8OH?6Kt#,ZYF!6;")$i~> +GatU4=`<=Y&:XAWcsq[]$q]8D;4uds6&MC<]^8)8#MPngTou@>-p-9m?V7WAThN""'L?1=O1FGC@@$64&*qoH)0'ibpMgsYKUj4ke6gPj^+WaK6]k;gB/BF%[f#.F%kHN\<:-d9)=DEOog>8.VGC'>4_J%[J),tPhHA3sbM>e?"d:V6pWh[AqT$u0QQYa;BfJ(ZSg8g254eS*P931s9$M+Upf8%MZVnBab*?@&03f6YAqIoZSL?aIjB:J";a6-O^+fNbO]@TM]?U/tUAW5N0p2N;RqYG[La"6]6I6fM'DK1*7fl5O?o)V%fMI&;)gs.;f)JXi9U%(u5QCgTb9YgtA[#M+h1lEJ/5!Wd1-5If%kMYp9g2j!kF,pmU'\AcqV(SNR&mUj/TLRO2K'8#+PTI@-9<)2hV:q.mX[*(>ASPdBp%]LS!.hF.ntYIhju/=,#=JeT'%K7oQ']MG?n?76ne:A&\Cn+X:t'6qYlgU7MVAs@5VGuD?q$=8cr1UW!7l+th.nJPgU?#bn*npm>:qFUmWghO.RVE\.$L,m./0#hE'XI?fd'egG!X61_Z:E=\TC"M%Z>&ZB#3b^3%-Qep(EsWCWLU:ag3lhS`bmmB`S4q81.tWYQ4g.&hR=%LZII*p>?N/25_Zp=!@.N"nH99"/S_d6k/=[.j7doViW0HkPRb_+5rT^)(a,j@Q-)Rm'MOjNeW$!2MZ_j/;*u?-XCIhOmq8Cfa1'o*g#>m:&?nXc_Gmgd?lE5eOS[+W.d%H[WB:7rb30HML';3J(F']iK_]7%,^<)J]Gi#r1/*WHjka,"'Y&&^uVoo',DkR\9t%g^'11l@C\#(p\8:^K?t74).r?T(_Rj39n8of!./;?K&WBJF(uVbRd5,1ebo%J8MA+#QpWC^Z0dB_#!a$R%=NE_,l`.(GdkG"t:n_-XIB"jQQQ,"Q#Vj'oMn7I%M+4553u64fCJUPDJY`o-Ee_Uir5mTE5cm(ur:0)e.aA's<\^^d&.\/`,BjmiN;aXbAN:BS%H>^l7)edu')$CPg`-7Rfc/(jP*r/^/SO.j(*P+nW"H&@M2W\)^5gpei/d.cr#rG'Fm"GAGeP(X:_ki#;:Bi_GieM12Kc8U\.`pTg]k7SF=cOukdSLuce;97lCY6O>gl$P-,VC8t*fTls;H%nf0FUeu##la:]B,m"ZnSGVDC.&< endstream endobj 104 0 obj @@ -978,133 +978,133 @@ 23 0 obj << /S /GoTo -/D [74 0 R /XYZ 85.0 150.666 null] +/D [76 0 R /XYZ 85.0 659.0 null] >> endobj 25 0 obj << /S /GoTo -/D [76 0 R /XYZ 85.0 489.8 null] +/D [76 0 R /XYZ 85.0 458.666 null] >> endobj 27 0 obj << /S /GoTo -/D [76 0 R /XYZ 85.0 458.666 null] +/D [76 0 R /XYZ 85.0 427.532 null] >> endobj 29 0 obj << /S /GoTo -/D [76 0 R /XYZ 85.0 394.213 null] +/D [76 0 R /XYZ 85.0 363.079 null] >> endobj 31 0 obj << /S /GoTo -/D [76 0 R /XYZ 85.0 321.76 null] +/D [76 0 R /XYZ 85.0 290.626 null] >> endobj 33 0 obj << /S /GoTo -/D [76 0 R /XYZ 85.0 249.307 null] +/D [76 0 R /XYZ 85.0 218.173 null] >> endobj 35 0 obj << /S /GoTo -/D [78 0 R /XYZ 85.0 245.8 null] +/D [78 0 R /XYZ 85.0 203.4 null] >> endobj 37 0 obj << /S /GoTo -/D [78 0 R /XYZ 85.0 194.547 null] +/D [78 0 R /XYZ 85.0 152.147 null] >> endobj 39 0 obj << /S /GoTo -/D [80 0 R /XYZ 85.0 637.8 null] +/D [80 0 R /XYZ 85.0 603.4 null] >> endobj 41 0 obj << /S /GoTo -/D [80 0 R /XYZ 85.0 585.466 null] +/D [80 0 R /XYZ 85.0 551.066 null] >> endobj 43 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 637.8 null] +/D [84 0 R /XYZ 85.0 547.8 null] >> endobj 45 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 499.347 null] +/D [84 0 R /XYZ 85.0 409.347 null] >> endobj 47 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 421.694 null] +/D [84 0 R /XYZ 85.0 331.694 null] >> endobj 49 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 169.241 null] +/D [86 0 R /XYZ 85.0 611.4 null] >> endobj 51 0 obj << /S /GoTo -/D [86 0 R /XYZ 85.0 659.0 null] +/D [86 0 R /XYZ 85.0 559.066 null] >> endobj 56 0 obj << /S /GoTo -/D [88 0 R /XYZ 85.0 409.4 null] +/D [88 0 R /XYZ 85.0 303.4 null] >> endobj 58 0 obj << /S /GoTo -/D [92 0 R /XYZ 85.0 383.8 null] +/D [92 0 R /XYZ 85.0 259.4 null] >> endobj 60 0 obj << /S /GoTo -/D [94 0 R /XYZ 85.0 154.2 null] +/D [96 0 R /XYZ 85.0 484.6 null] >> endobj 62 0 obj << /S /GoTo -/D [96 0 R /XYZ 85.0 230.2 null] +/D [98 0 R /XYZ 85.0 521.4 null] >> endobj 64 0 obj << /S /GoTo -/D [98 0 R /XYZ 85.0 287.0 null] +/D [100 0 R /XYZ 85.0 586.2 null] >> endobj 66 0 obj << /S /GoTo -/D [102 0 R /XYZ 85.0 478.6 null] +/D [102 0 R /XYZ 85.0 232.2 null] >> endobj 68 0 obj << /S /GoTo -/D [104 0 R /XYZ 85.0 547.8 null] +/D [104 0 R /XYZ 85.0 304.2 null] >> endobj 105 0 obj @@ -1115,147 +1115,147 @@ xref 0 142 0000000000 65535 f -0000048762 00000 n -0000048957 00000 n -0000049050 00000 n +0000049580 00000 n +0000049775 00000 n +0000049868 00000 n 0000000015 00000 n 0000000071 00000 n -0000001278 00000 n -0000001398 00000 n -0000001570 00000 n -0000049202 00000 n -0000001705 00000 n -0000049265 00000 n -0000001840 00000 n -0000049331 00000 n -0000001977 00000 n -0000049395 00000 n -0000002114 00000 n -0000049461 00000 n -0000002251 00000 n -0000049527 00000 n -0000002388 00000 n -0000049593 00000 n -0000002525 00000 n -0000049657 00000 n -0000002662 00000 n -0000049723 00000 n -0000002799 00000 n -0000049787 00000 n -0000002936 00000 n -0000049853 00000 n -0000003073 00000 n -0000049919 00000 n -0000003210 00000 n -0000049984 00000 n -0000003347 00000 n -0000050050 00000 n -0000003484 00000 n -0000050114 00000 n -0000003620 00000 n -0000050180 00000 n -0000003757 00000 n -0000050244 00000 n -0000003893 00000 n -0000050310 00000 n -0000004030 00000 n -0000050374 00000 n -0000004167 00000 n -0000050440 00000 n -0000004303 00000 n -0000050506 00000 n -0000004440 00000 n -0000050572 00000 n -0000004576 00000 n -0000005295 00000 n -0000005418 00000 n -0000005487 00000 n -0000050636 00000 n -0000005620 00000 n -0000050700 00000 n -0000005753 00000 n -0000050764 00000 n -0000005886 00000 n -0000050828 00000 n -0000006019 00000 n -0000050892 00000 n -0000006152 00000 n -0000050956 00000 n -0000006284 00000 n -0000051021 00000 n -0000006417 00000 n -0000008565 00000 n -0000008673 00000 n -0000010824 00000 n -0000010932 00000 n -0000013213 00000 n -0000013321 00000 n -0000015397 00000 n -0000015505 00000 n -0000017954 00000 n -0000018062 00000 n -0000019976 00000 n -0000020084 00000 n -0000022332 00000 n -0000022440 00000 n -0000024478 00000 n -0000024586 00000 n -0000026054 00000 n -0000026162 00000 n -0000027546 00000 n -0000027654 00000 n -0000029555 00000 n -0000029663 00000 n -0000031393 00000 n -0000031501 00000 n -0000033685 00000 n -0000033793 00000 n -0000035576 00000 n -0000035684 00000 n -0000037629 00000 n -0000037737 00000 n -0000039143 00000 n -0000039252 00000 n -0000041151 00000 n -0000041261 00000 n -0000042475 00000 n -0000051086 00000 n -0000042585 00000 n -0000042785 00000 n -0000043003 00000 n -0000043209 00000 n -0000043417 00000 n -0000043585 00000 n -0000043785 00000 n -0000043943 00000 n -0000044118 00000 n -0000044359 00000 n -0000044488 00000 n -0000044642 00000 n -0000044796 00000 n -0000044940 00000 n -0000045090 00000 n -0000045231 00000 n -0000045471 00000 n -0000045653 00000 n -0000045826 00000 n -0000046029 00000 n -0000046217 00000 n -0000046469 00000 n -0000046610 00000 n -0000046819 00000 n -0000047005 00000 n -0000047179 00000 n -0000047424 00000 n -0000047615 00000 n -0000047821 00000 n -0000047982 00000 n -0000048096 00000 n -0000048207 00000 n -0000048319 00000 n -0000048428 00000 n -0000048535 00000 n -0000048652 00000 n +0000001280 00000 n +0000001400 00000 n +0000001572 00000 n +0000050020 00000 n +0000001707 00000 n +0000050083 00000 n +0000001842 00000 n +0000050149 00000 n +0000001979 00000 n +0000050213 00000 n +0000002116 00000 n +0000050279 00000 n +0000002253 00000 n +0000050345 00000 n +0000002390 00000 n +0000050411 00000 n +0000002527 00000 n +0000050475 00000 n +0000002664 00000 n +0000050539 00000 n +0000002801 00000 n +0000050605 00000 n +0000002938 00000 n +0000050671 00000 n +0000003075 00000 n +0000050737 00000 n +0000003212 00000 n +0000050803 00000 n +0000003349 00000 n +0000050869 00000 n +0000003486 00000 n +0000050933 00000 n +0000003622 00000 n +0000050999 00000 n +0000003759 00000 n +0000051063 00000 n +0000003895 00000 n +0000051129 00000 n +0000004032 00000 n +0000051193 00000 n +0000004169 00000 n +0000051259 00000 n +0000004305 00000 n +0000051325 00000 n +0000004442 00000 n +0000051389 00000 n +0000004578 00000 n +0000005297 00000 n +0000005420 00000 n +0000005489 00000 n +0000051455 00000 n +0000005622 00000 n +0000051519 00000 n +0000005755 00000 n +0000051583 00000 n +0000005888 00000 n +0000051647 00000 n +0000006021 00000 n +0000051711 00000 n +0000006154 00000 n +0000051776 00000 n +0000006286 00000 n +0000051841 00000 n +0000006419 00000 n +0000008567 00000 n +0000008675 00000 n +0000010826 00000 n +0000010934 00000 n +0000013257 00000 n +0000013365 00000 n +0000015438 00000 n +0000015546 00000 n +0000017945 00000 n +0000018053 00000 n +0000020046 00000 n +0000020154 00000 n +0000022282 00000 n +0000022390 00000 n +0000024489 00000 n +0000024597 00000 n +0000026292 00000 n +0000026400 00000 n +0000027775 00000 n +0000027883 00000 n +0000029672 00000 n +0000029780 00000 n +0000031553 00000 n +0000031661 00000 n +0000033627 00000 n +0000033735 00000 n +0000035741 00000 n +0000035849 00000 n +0000037879 00000 n +0000037987 00000 n +0000039572 00000 n +0000039681 00000 n +0000041471 00000 n +0000041581 00000 n +0000043293 00000 n +0000051906 00000 n +0000043403 00000 n +0000043603 00000 n +0000043821 00000 n +0000044027 00000 n +0000044235 00000 n +0000044403 00000 n +0000044603 00000 n +0000044761 00000 n +0000044936 00000 n +0000045177 00000 n +0000045306 00000 n +0000045460 00000 n +0000045614 00000 n +0000045758 00000 n +0000045908 00000 n +0000046049 00000 n +0000046289 00000 n +0000046471 00000 n +0000046644 00000 n +0000046847 00000 n +0000047035 00000 n +0000047287 00000 n +0000047428 00000 n +0000047637 00000 n +0000047823 00000 n +0000047997 00000 n +0000048242 00000 n +0000048433 00000 n +0000048639 00000 n +0000048800 00000 n +0000048914 00000 n +0000049025 00000 n +0000049137 00000 n +0000049246 00000 n +0000049353 00000 n +0000049470 00000 n trailer << /Size 142 @@ -1263,5 +1263,5 @@ /Info 4 0 R >> startxref -51140 +51960 %%EOF Index: docs/fileformats.html =================================================================== --- docs/fileformats.html (revision 678362) +++ docs/fileformats.html (working copy) @@ -575,7 +575,7 @@

    Term Frequency data. For each term in the dictionary, the numbers of all the documents that contain that term, and the frequency of the term in - that document. + that document if omitTf is false.

    @@ -585,7 +585,9 @@

    Term Proximity data. For each term in the dictionary, the positions that the term - occurs in each document. + occurs in each document. Note that this will + not exist if all fields in all documents set + omitTf to true.

    @@ -1325,10 +1327,11 @@ 2.4 and above: Segments --> Format, Version, NameCounter, SegCount, <SegName, SegSize, DelGen, DocStoreOffset, [DocStoreSegment, DocStoreIsCompoundFile], HasSingleNormFile, NumField, NormGenNumField, - IsCompoundFile>SegCount, Checksum + IsCompoundFile, DeletionCount, HasProx>SegCount, Checksum

    - Format, NameCounter, SegCount, SegSize, NumField, DocStoreOffset --> Int32 + Format, NameCounter, SegCount, SegSize, NumField, + DocStoreOffset, DeletionCount --> Int32

    Version, DelGen, NormGen, Checksum --> Int64 @@ -1337,7 +1340,8 @@ SegName, DocStoreSegment --> String

    - IsCompoundFile, HasSingleNormFile, DocStoreIsCompoundFile --> Int8 + IsCompoundFile, HasSingleNormFile, + DocStoreIsCompoundFile, HasProx --> Int8

    Format is -1 as of Lucene 1.4, -3 (SegmentInfos.FORMAT_SINGLE_NORM_FILE) as of Lucene 2.1 and 2.2, -4 (SegmentInfos.FORMAT_SHARED_DOC_STORE) as of Lucene 2.3 and -5 (SegmentInfos.FORMAT_CHECKSUM) as of Lucene 2.4. @@ -1419,7 +1423,15 @@ This is used to verify integrity of the file on opening the index.

    - +

    + DeletionCount records the number of deleted + documents in this segment. +

    +

    + HasProx is 1 if any fields in this segment have + omitTf set to false; else, it's 0. +

    +

    Lock File

    The write lock, which is stored in the index @@ -1437,7 +1449,7 @@ Note that prior to version 2.1, Lucene also used a commit lock. This was removed in 2.1.

    - +

    Deletable File

    Prior to Lucene 2.1 there was a file "deletable" @@ -1446,7 +1458,7 @@ the files that are deletable, instead, so no file is written.

    - +

    Compound Files

    Starting with Lucene 1.4 the compound file format became default. This is simply a container for all files described in the next section @@ -1473,14 +1485,14 @@ - +

    Per-Segment Files

    The remaining files are all per-segment, and are thus defined by suffix.

    - +

    Fields

    @@ -1699,7 +1711,7 @@ - +

    Term Dictionary

    The term dictionary is represented as two files: @@ -1801,7 +1813,9 @@ determines the position of this term's TermPositions within the .prx file. In particular, it is the difference between the position of this term's data in that file and the position of the previous - term's data (or zero, for the first term in the file. + term's data (or zero, for the first term in the file. For fields + with omitTf true, this will be 0 since + prox information is not stored.

    SkipDelta determines the position of this @@ -1887,12 +1901,12 @@ - +

    Frequencies

    The .frq file contains the lists of documents which contain each term, along with the frequency of the term in that - document. + document (if omitTf is false).

    FreqFile (.frq) --> <TermFreqs, SkipData> @@ -1905,7 +1919,7 @@

    TermFreq --> - DocDelta, Freq? + DocDelta[, Freq?]

    SkipData --> <<SkipLevelLength, SkipLevel> @@ -1932,21 +1946,31 @@

    TermFreq entries are ordered by increasing document number.

    -

    DocDelta - determines both the document number and the frequency. In - particular, DocDelta/2 is the difference between this document number - and the previous document number (or zero when this is the first - document in a TermFreqs). When DocDelta is odd, the frequency is - one. When DocDelta is even, the frequency is read as another VInt. +

    DocDelta: if omitTf is false, this determines both + the document number and the frequency. In + particular, DocDelta/2 is the difference between + this document number and the previous document + number (or zero when this is the first document in + a TermFreqs). When DocDelta is odd, the frequency + is one. When DocDelta is even, the frequency is + read as another VInt. If omitTf is true, DocDelta + contains the gap (not multiplied by 2) between + document numbers and no frequency information is + stored.

    -

    For - example, the TermFreqs for a term which occurs once in document seven - and three times in document eleven would be the following sequence of - VInts: +

    For example, the TermFreqs for a term which occurs + once in document seven and three times in document + eleven, with omitTf false, would be the following + sequence of VInts:

    -

    15, - 8, 3 +

    15, 8, 3

    +

    If omitTf were true it would be this sequence + of VInts instead: +

    +

    + 7,4 +

    DocSkip records the document number before every SkipInterval th @@ -2005,11 +2029,15 @@ entry in level-1. In the example has entry 15 on level 1 a pointer to entry 15 on level 0 and entry 31 on level 1 a pointer to entry 31 on level 0.

    - +

    Positions

    The .prx file contains the lists of positions that - each term occurs at within documents. + each term occurs at within documents. Note that + fields with omitTf true do not store + anything into this file, and if all fields in the + index have omitTf true then the .prx file will not + exist.

    ProxFile (.prx) --> <TermPositions> @@ -2071,7 +2099,7 @@ Payload. If PayloadLength is not stored, then this Payload has the same length as the Payload at the previous position.

    - +

    Normalization Factors

    @@ -2175,7 +2203,7 @@ 2.1 and above: Separate norm files are created (when adequate) for both compound and non compound segments.

    - +

    Term Vectors

    Term Vector support is an optional on a field by @@ -2308,7 +2336,7 @@ - +

    Deleted Documents

    The .del file is optional, and only exists when a segment contains deletions. @@ -2380,7 +2408,7 @@

    - +

    Limitations

    There