source: trunk/CrypPlugins/CostFunction/CostFunction.cs @ 1710

Last change on this file since 1710 was 1710, checked in by malischewski, 12 years ago

Fixed bug which broke weighted bigrams/trigrams costfunction. actually works now.

File size: 33.8 KB
Line 
1/*                             
2   Copyright 2009 Team CrypTool (Sven Rech,Dennis Nolte,Raoul Falk,Nils Kopal), Uni Duisburg-Essen
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.Collections.Generic;
19using System.Collections;
20using System.Linq;
21using System.Text;
22using Cryptool.PluginBase.Cryptography;
23using Cryptool.PluginBase;
24using Cryptool.PluginBase.Miscellaneous;
25using Cryptool.PluginBase.Analysis;
26using System.ComponentModel;
27using Cryptool.PluginBase.Control;
28using System.IO;
29using System.Text.RegularExpressions;
30using System.Threading;
31using System.Reflection;
32namespace Cryptool.Plugins.CostFunction
33{
34    [Author("Nils Kopal", "Nils.Kopal@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
35    [PluginInfo(false, "CostFunction", "CostFunction", null, "CostFunction/icon.png")]
36    public class CostFunction : IAnalysisMisc
37    {
38        #region private variables
39        private CostFunctionSettings settings = new CostFunctionSettings();
40        private byte[] inputText = null;
41        private byte[] outputText = null;
42        private double value = 0;
43        private Boolean stopped = true;
44        private IControlCost controlSlave;
45        private String bigramInput;
46        private double[,] bigramMatrix;
47        private IDictionary<string, double[]> corpusGrams;
48
49        private IDictionary<string, double[]> corpusBigrams; // Used for Weighted Bigrams/Trigrams Cost function
50        private IDictionary<string, double[]> corpusTrigrams;
51
52        //Fitness Weight Tables for Weighted Bigrams/Trigrams
53        private IDictionary<string, double> fwtMatthews = new Dictionary<string,double>();
54        private IDictionary<string, double> fwtAndrewJohnClark = new Dictionary<string,double>();
55        private IDictionary<string, double> fwtToemehArumugam = new Dictionary<string,double>();
56
57        private double betaMatthews = 1.0;
58        private double gammaMatthews = 1.0;
59
60        private double betaToemehArumugam = 1.0;
61        private double gammaToemehArumugam = 1.0;
62
63        private DataManager dataMgr = new DataManager(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); 
64        private const string DATATYPE = "transposition";
65
66        private IDictionary<String, DataFileMetaInfo> txtList;
67        private IDictionary<int, IDictionary<string, double[]>> statistics;
68
69        #endregion
70        #region internal constants
71        internal const int ABSOLUTE = 0;
72        internal const int PERCENTAGED = 1;
73        internal const int LOG2 = 2;
74        internal const int SINKOV = 3;
75        #endregion
76        #region CostFunctionInOut
77
78        [PropertyInfo(Direction.InputData, "Text Input", "Input your Text here", "", DisplayLevel.Beginner)]
79        public byte[] InputText
80        {
81            get
82            {
83                return inputText;
84            }
85            set
86            {
87                this.inputText = value;
88                OnPropertyChanged("InputText");
89            }
90        }
91
92        [PropertyInfo(Direction.OutputData, "Text Output", "Your Text will be send here", "", DisplayLevel.Beginner)]
93        public byte[] OutputText
94        {
95            get
96            {
97                return outputText;
98            }
99            set
100            {
101                this.outputText = value;
102                OnPropertyChanged("OutputText");
103            }
104        }
105
106        [PropertyInfo(Direction.OutputData, "Value", "The value of the function will be send here", "", DisplayLevel.Beginner)]
107        public double Value
108        {
109            get
110            {
111                return value;
112            }
113            set
114            {
115                this.value = value;
116                OnPropertyChanged("Value");
117            }
118        }
119
120        [PropertyInfo(Direction.ControlSlave, "SDES Slave", "Direct access to SDES.", "", DisplayLevel.Beginner)]
121        public IControlCost ControlSlave
122        {
123            get
124            {
125                if (controlSlave == null)
126                    controlSlave = new CostFunctionControl(this);
127                return controlSlave;
128            }
129        }
130
131        #endregion
132
133        #region IPlugin Members
134
135        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
136        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
137
138
139        public ISettings Settings
140        {
141            get { return this.settings; }
142            set { this.settings = (CostFunctionSettings)value; }
143        }
144
145        public System.Windows.Controls.UserControl Presentation
146        {
147            get { return null; }
148        }
149
150        public System.Windows.Controls.UserControl QuickWatchPresentation
151        {
152            get { return null; }
153        }
154
155        public void PreExecution()
156        {
157            this.stopped = false;
158        }
159
160        public void Execute()
161        {
162            if (this.InputText is Object && this.stopped == false)
163            {
164                int bytesToUse = 0;
165                try
166                {
167                    bytesToUse = int.Parse(settings.BytesToUse);
168                }
169                catch (Exception ex)
170                {
171                    GuiLogMessage("Entered bytesToUse is not an integer: " + ex.Message, NotificationLevel.Error);
172                    return;
173                }
174
175                if (bytesToUse > this.InputText.Length)
176                {
177                    bytesToUse = 0;
178                }
179
180                byte[] array;
181
182                if (bytesToUse > 0)
183                {
184                    //Create a new Array of size of bytesToUse if needed
185                    array = new byte[bytesToUse];
186                    for (int i = 0; i < bytesToUse && i < this.InputText.Length; i++)
187                    {
188                        array[i] = InputText[i];
189                    }
190                }
191                else
192                {
193                    array = this.InputText;
194                }
195
196                ProgressChanged(0.5, 1);
197                bigramInput = ByteArrayToString(array);
198                switch (settings.FunctionType)
199                {
200
201                    case 0: // Index of Coincedence
202                        this.Value = calculateIndexOfCoincidence(array);
203                        break;
204
205                    case 1: // Entropy
206                        this.Value = calculateEntropy(array);
207                        break;
208
209                    case 2: // Log 2 Bigrams
210                        this.Value = calculateNGrams(bigramInput, 2, 2,false);
211                        break;
212
213                    case 3: // sinkov Bigrams
214                        this.Value = calculateNGrams(bigramInput, 2, 3,false);
215                        break;
216                    case 4: //percentaged Bigrams
217                        this.Value = calculateNGrams(bigramInput, 2, 1,false);
218                        break;
219                    case 5: //regular expressions
220                        this.Value = regex(bigramInput);
221                        break;
222                    case 6: // Weighted Bigrams/Trigrams (used by genetic algorithm in transposition analyser
223                        this.Value = calculateWeighted(bigramInput);
224                        break;
225
226                    default:
227                        this.Value = -1;
228                        break;
229                }//end switch               
230
231                this.OutputText = this.InputText;
232                ProgressChanged(1, 1);
233
234            }//end if
235
236        }
237
238
239
240        public void PostExecution()
241        {
242            this.stopped = true;
243        }
244
245        public void Pause()
246        {
247
248        }
249
250        public void Stop()
251        {
252            this.stopped = false;
253        }
254
255        public void Initialize()
256        {
257
258        }
259
260        public void Dispose()
261        {
262
263        }
264
265        #endregion
266
267        #region INotifyPropertyChanged Members
268
269        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
270
271        public void OnPropertyChanged(string name)
272        {
273            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
274        }
275
276        private void ProgressChanged(double value, double max)
277        {
278            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
279        }
280
281        public void GuiLogMessage(string p, NotificationLevel notificationLevel)
282        {
283            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(p, this, notificationLevel));
284        }
285
286        #endregion
287
288        #region IPlugin Members
289
290        public event StatusChangedEventHandler OnPluginStatusChanged;
291
292        #endregion
293
294        #region private methods
295
296        private void fillfwts() {
297            fwtMatthews.Add("TH", 2.0);
298            fwtMatthews.Add("HE", 1.0);
299            fwtMatthews.Add("IN", 1.0);
300            fwtMatthews.Add("ER", 1.0);
301            fwtMatthews.Add("AN", 1.0);
302            fwtMatthews.Add("ED", 1.0);
303            fwtMatthews.Add("THE", 5.0);
304            fwtMatthews.Add("ING", 5.0);
305            fwtMatthews.Add("AND", 5.0);
306            fwtMatthews.Add("EEE", -5.0);
307            //extension:
308            fwtToemehArumugam.Add("YYY", -5.0);
309            fwtToemehArumugam.Add("BBB", -5.0);
310            fwtToemehArumugam.Add("OOO", -5.0);
311            fwtToemehArumugam.Add("III", -5.0);
312            fwtToemehArumugam.Add("UUU", -5.0);
313            fwtToemehArumugam.Add("DDD", -5.0);
314            fwtToemehArumugam.Add("JJJ", -5.0);
315            fwtToemehArumugam.Add("QQQ", -5.0);
316            fwtToemehArumugam.Add("VVV", -5.0);
317            fwtToemehArumugam.Add("GGG", -5.0);
318
319            fwtToemehArumugam.Add("KKK", -2.0);
320            fwtToemehArumugam.Add("AAA", -2.0);
321            fwtToemehArumugam.Add("CCC", -2.0);
322            fwtToemehArumugam.Add("TTT", -2.0);
323
324            fwtToemehArumugam.Add("FFF", 0.0);
325            fwtToemehArumugam.Add("SSS", 0.0);
326            fwtToemehArumugam.Add("HHH", -5.0);
327            fwtToemehArumugam.Add("MMM", -5.0);
328            fwtToemehArumugam.Add("NNN", -5.0);
329            fwtToemehArumugam.Add("PPP", 0.0);
330            fwtToemehArumugam.Add("RRR", -5.0);
331            fwtToemehArumugam.Add("ZZZ", -5.0);
332            fwtToemehArumugam.Add("XXX", 5.0);
333            fwtToemehArumugam.Add("WWW", 5.0);
334
335            fwtToemehArumugam.Add("AUI", -5.0);
336            fwtToemehArumugam.Add("UAI", -5.0);
337            fwtToemehArumugam.Add("IAU", -5.0);
338            fwtToemehArumugam.Add("AIU", -5.0);
339            fwtToemehArumugam.Add("UUU", -5.0);
340            fwtToemehArumugam.Add("WV", -5.0);
341            fwtToemehArumugam.Add("VW", -5.0);
342            fwtToemehArumugam.Add("HC", -5.0);
343            fwtToemehArumugam.Add("ZR", -5.0);
344            fwtToemehArumugam.Add("RZ", -5.0);
345            fwtToemehArumugam.Add("ZX", -5.0);
346            fwtToemehArumugam.Add("XZ", -5.0);
347            fwtToemehArumugam.Add("J ", -5.0);
348            fwtToemehArumugam.Add("X ", -5.0);
349            fwtToemehArumugam.Add("Q ", -5.0);
350            fwtToemehArumugam.Add("QC", -5.0);
351            fwtToemehArumugam.Add("QJ", -5.0);
352            fwtToemehArumugam.Add("QW", -5.0);
353            fwtToemehArumugam.Add("QZ", -5.0);
354            fwtToemehArumugam.Add("QX", -5.0);
355            fwtToemehArumugam.Add("QY", -5.0);
356            fwtToemehArumugam.Add("QE", -5.0);
357            fwtToemehArumugam.Add("QI", -5.0);
358            fwtToemehArumugam.Add("QU", -5.0);
359            fwtToemehArumugam.Add("QO", -5.0);
360            fwtToemehArumugam.Add("JX", -5.0);
361            fwtToemehArumugam.Add("QV", -5.0);
362            fwtToemehArumugam.Add("ZJ", -5.0);
363
364
365            fwtToemehArumugam.Add("EEE", -5.0);
366            fwtToemehArumugam.Add("E ", 2.0);
367            fwtToemehArumugam.Add(" T", 1.0);
368            fwtToemehArumugam.Add("HE", 1.0);
369            fwtToemehArumugam.Add("TH", 1.0);
370            fwtToemehArumugam.Add(" A", 1.0);
371            fwtToemehArumugam.Add("   ", -10.0);
372            fwtToemehArumugam.Add("ING", 5.0);
373            fwtToemehArumugam.Add("S ", 1.0);
374            fwtToemehArumugam.Add("  ", -6.0);
375            fwtToemehArumugam.Add(" TH", 5.0);
376            fwtToemehArumugam.Add("THE", 5.0);
377            fwtToemehArumugam.Add("HE ", 5.0);
378            fwtToemehArumugam.Add("AND", 5.0);
379
380            fwtToemehArumugam.Add("ARE", 5.0);
381            fwtToemehArumugam.Add("NOT", 5.0);
382        }
383
384        private void weights(string ngram, int ngramlength)
385        {
386            if (fwtMatthews.TryGetValue(ngram, out value) && ngramlength == 2)
387            {
388                betaMatthews += value;
389            }
390
391            if (fwtMatthews.TryGetValue(ngram, out value) && ngramlength == 3)
392            {
393                gammaMatthews += value;
394            }
395
396
397            if (fwtToemehArumugam.TryGetValue(ngram, out value) && ngramlength == 2)
398            {
399                betaToemehArumugam += value;
400            }
401
402            if (fwtToemehArumugam.TryGetValue(ngram, out value) && ngramlength == 3)
403            {
404                gammaToemehArumugam += value;
405            }
406        }
407
408        //public double contains(string input)
409        //{
410        //    if (settings.Contains == null)
411        //    {
412        //        GuiLogMessage("There is no text to be searched for. Please insert text in the 'Contains text / Regular Expression' - Textarea", NotificationLevel.Error);
413        //        return new Double();
414        //    }
415
416        //    if (input.Contains(settings.Contains))
417        //    {
418        //        return 1.0;
419        //    }
420        //    return -1.0;
421        //}
422        public double calculateWeighted(string input)
423        {
424
425         
426
427            this.statistics = new Dictionary<int, IDictionary<string, double[]>>();
428
429            if (fwtMatthews == null && fwtToemehArumugam == null) { fillfwts(); }
430            if (corpusBigrams == null)
431            {
432                if (corpusTrigrams == null)
433                {
434
435                    corpusBigrams = GetStatistics(2); // Get Known Language statistics for Bigrams
436                    corpusTrigrams = GetStatistics(3); // and Trigrams
437                }
438
439            }
440            input = input.ToUpper();
441
442            double bigramscore = calculateNGrams(input, 2, 3, true); // Sinkov
443            double trigramscore = calculateNGrams(input, 3, 3, true);
444            //testweise
445           
446           // return  bigramscore + trigramscore;
447            return (betaToemehArumugam * bigramscore) + (gammaToemehArumugam * trigramscore);
448            //return betaToemehArumugam * bigramscore;
449
450            /*
451            Dictionary<string, double> inputBiGrams = new Dictionary<string,double>();
452            Dictionary<string, double> inputTriGrams = new Dictionary<string,double>();
453           
454            // Count input Bigrams
455            foreach (string g in GramTokenizer.tokenize(input, 2, false))
456            {
457                if (inputBiGrams.ContainsKey(g))
458                {
459                    inputBiGrams[g] = inputBiGrams[g] + 1;
460                    if (fwtMatthews.TryGetValue(g, out value))
461                    {
462                        beta += value;
463                    }
464                }
465                else
466                {
467                    inputBiGrams.Add(g, 0);
468                    if (fwtMatthews.TryGetValue(g, out value))
469                    {
470                        beta += value;
471                    }
472                }
473            }
474           
475             debug
476            foreach (KeyValuePair<string, double[]> g in corpusBigrams)
477            {
478                GuiLogMessage(corpusBigrams[g.Key][0].ToString() + " " + g.Key + " " + corpusBigrams[g.Key][1].ToString(), NotificationLevel.Debug);
479            }
480           
481            // Count input TriGrams
482            foreach (string g in GramTokenizer.tokenize(input, 3, false))
483            {
484                if (inputTriGrams.ContainsKey(g))
485                {
486                    inputTriGrams[g] = inputTriGrams[g] + 1;
487                }
488                else
489                {
490                    inputTriGrams.Add(g, 0);
491                }
492            }
493           
494            //Union Bigrams
495            HashSet<string> allBigrams = new HashSet<string>(inputBiGrams.Keys);
496            allBigrams.UnionWith(corpusBigrams.Keys);
497
498            //Union Trigrams
499            HashSet<string> allTrigrams = new HashSet<string>(inputTriGrams.Keys);
500            allTrigrams.UnionWith(corpusTrigrams.Keys);
501
502            // Sum of all input Bigrams absolutes
503            double sumBigrams = 0.0;
504
505            // Sum of all input Trigrams absolutes
506            double sumTrigrams = 0.0;
507
508            // First part of the equation: Sum up all [K_b (i,j) - D_b (i,j)]
509            double bigramscore = 0.0;
510            foreach (string g in allBigrams)
511            {
512                if (corpusBigrams.ContainsKey(g) && inputBiGrams.ContainsKey(g))
513                {
514                    sumBigrams++;
515                    bigramscore += corpusBigrams[g][1] - inputBiGrams[g] / sumBigrams;
516                   
517                }
518                else if (!corpusBigrams.ContainsKey(g))
519                {
520                    sumBigrams++;
521                    bigramscore += 0.0 - inputBiGrams[g] / sumBigrams;
522                   
523                }
524                else if (!inputBiGrams.ContainsKey(g))
525                {
526                    sumBigrams++;
527                    bigramscore += corpusBigrams[g][1];
528                   
529                }
530            }
531
532            // Second part of the equation: Sum up all [K_t (i,j) - D_t (i,j)]
533            double Trigramscore = 0.0;
534            foreach (string g in allTrigrams)
535            {
536                if (corpusTrigrams.ContainsKey(g) && inputTriGrams.ContainsKey(g))
537                {
538                    sumTrigrams++;
539                    Trigramscore += corpusTrigrams[g][1] - inputTriGrams[g] / sumTrigrams;
540                }
541                else if (!corpusTrigrams.ContainsKey(g))
542                {
543                    sumTrigrams++;
544                    Trigramscore += 0.0 - inputTriGrams[g] / sumTrigrams;
545                }
546                else if (!inputTriGrams.ContainsKey(g))
547                {
548                    sumTrigrams++;
549                    Trigramscore += corpusTrigrams[g][1];
550                }
551            }
552            double total = beta * bigramscore + gamma * Trigramscore;
553            if (total != 0.0)
554            {
555                GuiLogMessage(total.ToString(), NotificationLevel.Debug);
556            }
557            return total;
558            */
559        }//end Execute
560
561        public double regex(string input)
562        {
563            if (settings.RegEx == null)
564            {
565                GuiLogMessage("There is no Regular Expression to be searched for. Please insert regex in the 'Regular Expression' - Textarea", NotificationLevel.Error);
566                return new Double();
567            }
568            try
569            {
570                Match match = Regex.Match(input, settings.RegEx);
571                if (match.Success)
572                {
573                    return 1.0;
574                }
575                else
576                {
577                    return -1.0;
578                }
579            }
580            catch (Exception e)
581            {
582                GuiLogMessage(e.Message, NotificationLevel.Error);
583                return -1.0;
584            }
585
586        }
587
588
589        /// <summary>
590        /// Calculates the Index of Coincidence multiplied with 100 of
591        /// a given byte array
592        ///
593        /// for example a German text has about 7.62
594        ///           an English text has about 6.61
595        /// </summary>
596        /// <param name="text">text to use</param>
597        /// <returns>Index of Coincidence</returns>
598        public double calculateIndexOfCoincidence(byte[] text)
599        {
600            return calculateIndexOfCoincidence(text, text.Length);
601        }
602
603        /// <summary>
604        /// Calculates the Index of Coincidence multiplied with 100 of
605        /// a given byte array
606        ///
607        /// for example a German text has about 7.62
608        ///           an English text has about 6.61
609        /// </summary>
610        /// <param name="text">text to use</param>
611        /// <param name="text">bytesToUse</param>
612        /// <returns>Index of Coincidence</returns>
613        public double calculateIndexOfCoincidence(byte[] text, int bytesToUse)
614        {
615            if (bytesToUse > text.Length)
616                bytesToUse = text.Length;
617
618            double[] n = new double[256];
619            //count all ASCII symbols
620            int counter = 0;
621            foreach (byte b in text)
622            {
623                n[b]++;
624                counter++;
625                if (counter == bytesToUse)
626                    break;
627            }
628
629            double coindex = 0;
630            //sum them
631            for (int i = 0; i < n.Length; i++)
632            {
633                coindex = coindex + n[i] * (n[i] - 1);
634            }
635
636            coindex = coindex / (bytesToUse);
637            coindex = coindex / (bytesToUse - 1);
638
639            return coindex * 100;
640
641        }//end calculateIndexOfCoincidence
642
643
644        private int lastUsedSize = -1;
645        private double[] xlogx;
646        private Mutex prepareMutex = new Mutex();
647
648        private void prepareEntropy(int size)
649        {
650            xlogx = new double[size + 1];
651            //precomputations for fast entropy calculation     
652            xlogx[0] = 0.0;
653            for (int i = 1; i <= size; i++)
654                xlogx[i] = -1.0 * i * Math.Log(i / (double)size) / Math.Log(2.0);
655        }
656
657        /// <summary>
658        /// Calculates the Entropy of a given byte array
659        /// for example a German text has about 4.0629
660        /// </summary>
661        /// <param name="text">text to use</param>
662        /// <returns>Entropy</returns>
663        public double calculateEntropy(byte[] text)
664        {
665            return calculateEntropy(text, text.Length);
666        }
667
668        /// <summary>
669        /// Calculates the Entropy of a given byte array
670        /// for example a German text has about 4.0629
671        /// </summary>
672        /// <param name="text">text to use</param>
673        /// <returns>Entropy</returns>
674        public double calculateEntropy(byte[] text, int bytesToUse)
675        {
676            return NativeCryptography.Crypto.calculateEntropy(text, bytesToUse);
677            if (bytesToUse > text.Length)
678           
679                bytesToUse = text.Length;
680           
681            if (lastUsedSize != bytesToUse)
682            {
683                try
684                {
685                    prepareMutex.WaitOne();
686                    if (lastUsedSize != bytesToUse)
687                    {
688                        prepareEntropy(bytesToUse);
689                        lastUsedSize = bytesToUse;
690                    }
691                }
692                finally
693                {
694                    prepareMutex.ReleaseMutex();
695                }
696            }
697
698            int[] n = new int[256];
699            //count all ASCII symbols
700            for (int counter = 0; counter < bytesToUse; counter++)
701            {
702                n[text[counter]]++;
703            }
704
705            double entropy = 0;
706            //calculate probabilities and sum entropy
707            for (int i = 0; i < 256; i++)
708                entropy += xlogx[n[i]];
709
710            return entropy / (double)bytesToUse;
711
712        }//end calculateEntropy
713
714        /// <summary>
715        /// This method calculates a trigram log2 score of a given text on the basis of a given grams dictionary.
716        /// Case is insensitive.
717        /// </summary>
718        /// <param name="input">The text to be scored</param>
719        /// <param name="length">n-gram length</param>
720        /// <returns>The trigram score result</returns>
721        public double calculateNGrams(string input, int length, int valueSelection, bool weighted)
722        {
723
724            this.statistics = new Dictionary<int, IDictionary<string, double[]>>();
725            double score = 0;
726            if (corpusBigrams == null && length == 2)
727            { corpusBigrams = GetStatistics(length); }
728
729            if (corpusTrigrams == null && length == 3)
730            { corpusTrigrams = GetStatistics(length); }
731            input = input.ToUpper();
732            // FIXME: case handling?
733
734            HashSet<string> inputGrams = new HashSet<string>();
735
736            foreach (string g in GramTokenizer.tokenize(input, length, false))
737            {
738                // ensure each n-gram is counted only once
739                if (inputGrams.Add(g))
740                {
741                    if (corpusBigrams.ContainsKey(g) && length == 2 )
742                    {
743                        score += corpusBigrams[g][valueSelection];
744                        if (weighted) { weights(g, 2); }
745                    }
746                    if (length == 3 )
747                    {
748                        if (corpusTrigrams.ContainsKey(g))
749                        {
750                            score += corpusTrigrams[g][valueSelection];
751                            if (weighted) { weights(g, 3); }
752                        }
753                    }
754                }
755            }
756
757            return score;
758        }
759        public IDictionary<string, double[]> GetStatistics(int gramLength)
760        {
761            // FIXME: inputTriGrams is not being used!
762
763            // FIXME: implement exception handling
764            if (!statistics.ContainsKey(gramLength))
765            {
766                //GuiLogMessage("Trying to load default statistics for " + gramLength + "-grams", NotificationLevel.Info);
767                statistics[gramLength] = LoadDefaultStatistics(gramLength);
768            }
769
770            return statistics[gramLength];
771        }
772
773        private IDictionary<string, double[]> LoadDefaultStatistics(int length)
774        {
775           
776            txtList = dataMgr.LoadDirectory(DATATYPE);
777           
778            switch (this.settings.StatisticsCorpus)
779            {
780                case 0:
781                    return calculateAbsolutes(txtList["statisticscorpusde"].DataFile.FullName, length);
782                   
783                case 1:
784                    return calculateAbsolutes(txtList["statisticscorpusen"].DataFile.FullName, length);
785                case 2:
786                    return calculateAbsolutes(this.settings.customFilePath, length);
787                //to prevent a poss. initial-err
788                //default:
789                //    return calculateAbsolutes(txtList["statisticscorpusen"].DataFile.FullName, length);
790
791            }
792            return calculateAbsolutes(txtList["statisticscorpusde"].DataFile.FullName, length); //default
793           
794        }
795
796        private IDictionary<string, double[]> calculateAbsolutes(String path, int length)
797        {
798
799
800            Dictionary<string, double[]> grams = new Dictionary<string, double[]>();
801            int checkLength;
802            StreamReader reader = new StreamReader(path);
803            String text = reader.ReadToEnd();
804
805            text.ToUpper();
806            text = Regex.Replace(text, "[^A-Z]*", "");
807
808            if (length == 2)
809            {
810                checkLength = text.Length - 1;
811            }
812            else
813            {
814                checkLength = text.Length - 2;
815            }
816            for (int i = 0; i < checkLength; i++)
817            {
818                char a = text[i];
819                char b = text[i + 1];
820                String key;
821                if (length == 3) // Trigrams
822                {
823                    char c = text[i + 2];
824                    key = a.ToString();
825                    key = key + b.ToString();
826                    key = key + c.ToString();
827                }
828                else // Bigrams
829                {
830                    key = a.ToString();
831                    key = key + b.ToString();
832                }
833
834                if (!grams.ContainsKey(key))
835                {
836                    grams.Add(key, new double[] { 1, 0, 0, 0}); 
837                }
838                else
839                {
840                    grams[key][0] = grams[key][0] + 1.0;
841                }
842            }
843
844            double sum = grams.Values.Sum(item => item[ABSOLUTE]);
845            GuiLogMessage("Sum of all n-gram counts is: " + sum, NotificationLevel.Debug);
846
847            // calculate scaled values
848            foreach (double[] g in grams.Values)
849            {
850                g[PERCENTAGED] = g[ABSOLUTE] / sum;
851                g[LOG2] = Math.Log(g[ABSOLUTE], 2);
852                g[SINKOV] = Math.Log(g[PERCENTAGED], Math.E);
853            }
854
855
856
857            return grams;
858        }
859
860        public string ByteArrayToString(byte[] arr)
861        {
862            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
863            return enc.GetString(arr);
864        }
865
866
867        #endregion
868
869
870    }
871
872    #region slave
873
874    public class CostFunctionControl : IControlCost
875    {
876        public event IControlStatusChangedEventHandler OnStatusChanged;
877        #region IControlCost Members
878
879        private CostFunction plugin;
880
881        #endregion
882
883        /// <summary>
884        /// Constructor
885        /// </summary>
886        /// <param name="plugin"></param>
887        public CostFunctionControl(CostFunction plugin)
888        {
889            this.plugin = plugin;
890        }
891
892        public int getBytesToUse()
893        {
894            try
895            {
896                return int.Parse(((CostFunctionSettings)this.plugin.Settings).BytesToUse);
897            }
898            catch (Exception ex)
899            {
900                throw new Exception("Entered bytesToUse is not an integer: " + ex.Message);
901            }
902        }
903
904        /// <summary>
905        /// Returns the relation operator of the cost function which is set by by CostFunctionSettings
906        /// </summary>
907        /// <returns>RelationOperator</returns>
908        public RelationOperator getRelationOperator()
909        {
910            switch (((CostFunctionSettings)this.plugin.Settings).FunctionType)
911            {
912                case 0: //Index of coincidence
913                    return RelationOperator.LargerThen;
914                case 1: //Entropy
915                    return RelationOperator.LessThen;
916                case 2: // Bigrams: log 2
917                    return RelationOperator.LessThen;
918                case 3: // Sinkov
919                    return RelationOperator.LargerThen;
920                case 4: // percentage
921                    return RelationOperator.LargerThen;
922                case 5: // Regular Expression
923                    return RelationOperator.LargerThen;
924                case 6: // Weighted Bigrams/Trigrams
925                    return RelationOperator.LargerThen;
926
927                default:
928                    throw new NotImplementedException("The value " + ((CostFunctionSettings)this.plugin.Settings).FunctionType + " is not implemented.");
929            }//end switch
930        }//end getRelationOperator
931
932        /// <summary>
933        /// Calculates the cost function of the given text
934        ///
935        /// Cost function can be set by CostFunctionSettings
936        /// This algorithm uses a bytesToUse which can be set by CostFunctionSettings
937        /// If bytesToUse is set to 0 it uses the whole text
938        ///
939        /// </summary>
940        /// <param name="text"></param>
941        /// <returns>cost</returns>
942        public double calculateCost(byte[] text)
943        {
944            int bytesToUse = 0;
945            try
946            {
947                bytesToUse = ((CostFunctionSettings)this.plugin.Settings).BytesToUseInteger;
948            }
949            catch (Exception ex)
950            {
951                throw new Exception("Entered bytesToUse is not an integer: " + ex.Message);
952            }
953
954            switch (((CostFunctionSettings)this.plugin.Settings).FunctionType)
955            {
956                case 0: //Index of coincidence
957                    return plugin.calculateIndexOfCoincidence(text, bytesToUse);
958                case 1: //Entropy
959                    return plugin.calculateEntropy(text, bytesToUse);
960                case 2: // Bigrams: log 2
961                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 2, false);
962                case 3: // Bigrams: Sinkov
963                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 3, false);
964                case 4: // Bigrams: Percentaged
965                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 1, false);
966                case 5: // regular expression
967                    return plugin.regex(plugin.ByteArrayToString(text));
968                case 6:
969                    return plugin.calculateWeighted(plugin.ByteArrayToString(text));
970                default:
971                    throw new NotImplementedException("The value " + ((CostFunctionSettings)this.plugin.Settings).FunctionType + " is not implemented.");
972            }//end switch
973        }
974
975
976    #endregion
977    }
978
979}
980
Note: See TracBrowser for help on using the repository browser.