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

Last change on this file since 1598 was 1598, checked in by wiefels, 12 years ago

crashbug fixed.

weight-tables extended.
results from weighted bi-/trigram analysis still unsatisfying.

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, 0, true);
443            double trigramscore = calculateNGrams(input, 3, 0, true);
444            //testweise
445            return 1.0*betaToemehArumugam * bigramscore +  betaToemehArumugam*trigramscore;
446            // return -(4*(betaToemehArumugam * bigramscore) + 6*(betaToemehArumugam * trigramscore));
447            //return betaToemehArumugam * bigramscore;
448
449            /*
450            Dictionary<string, double> inputBiGrams = new Dictionary<string,double>();
451            Dictionary<string, double> inputTriGrams = new Dictionary<string,double>();
452           
453            // Count input Bigrams
454            foreach (string g in GramTokenizer.tokenize(input, 2, false))
455            {
456                if (inputBiGrams.ContainsKey(g))
457                {
458                    inputBiGrams[g] = inputBiGrams[g] + 1;
459                    if (fwtMatthews.TryGetValue(g, out value))
460                    {
461                        beta += value;
462                    }
463                }
464                else
465                {
466                    inputBiGrams.Add(g, 0);
467                    if (fwtMatthews.TryGetValue(g, out value))
468                    {
469                        beta += value;
470                    }
471                }
472            }
473           
474             debug
475            foreach (KeyValuePair<string, double[]> g in corpusBigrams)
476            {
477                GuiLogMessage(corpusBigrams[g.Key][0].ToString() + " " + g.Key + " " + corpusBigrams[g.Key][1].ToString(), NotificationLevel.Debug);
478            }
479           
480            // Count input TriGrams
481            foreach (string g in GramTokenizer.tokenize(input, 3, false))
482            {
483                if (inputTriGrams.ContainsKey(g))
484                {
485                    inputTriGrams[g] = inputTriGrams[g] + 1;
486                }
487                else
488                {
489                    inputTriGrams.Add(g, 0);
490                }
491            }
492           
493            //Union Bigrams
494            HashSet<string> allBigrams = new HashSet<string>(inputBiGrams.Keys);
495            allBigrams.UnionWith(corpusBigrams.Keys);
496
497            //Union Trigrams
498            HashSet<string> allTrigrams = new HashSet<string>(inputTriGrams.Keys);
499            allTrigrams.UnionWith(corpusTrigrams.Keys);
500
501            // Sum of all input Bigrams absolutes
502            double sumBigrams = 0.0;
503
504            // Sum of all input Trigrams absolutes
505            double sumTrigrams = 0.0;
506
507            // First part of the equation: Sum up all [K_b (i,j) - D_b (i,j)]
508            double bigramscore = 0.0;
509            foreach (string g in allBigrams)
510            {
511                if (corpusBigrams.ContainsKey(g) && inputBiGrams.ContainsKey(g))
512                {
513                    sumBigrams++;
514                    bigramscore += corpusBigrams[g][1] - inputBiGrams[g] / sumBigrams;
515                   
516                }
517                else if (!corpusBigrams.ContainsKey(g))
518                {
519                    sumBigrams++;
520                    bigramscore += 0.0 - inputBiGrams[g] / sumBigrams;
521                   
522                }
523                else if (!inputBiGrams.ContainsKey(g))
524                {
525                    sumBigrams++;
526                    bigramscore += corpusBigrams[g][1];
527                   
528                }
529            }
530
531            // Second part of the equation: Sum up all [K_t (i,j) - D_t (i,j)]
532            double Trigramscore = 0.0;
533            foreach (string g in allTrigrams)
534            {
535                if (corpusTrigrams.ContainsKey(g) && inputTriGrams.ContainsKey(g))
536                {
537                    sumTrigrams++;
538                    Trigramscore += corpusTrigrams[g][1] - inputTriGrams[g] / sumTrigrams;
539                }
540                else if (!corpusTrigrams.ContainsKey(g))
541                {
542                    sumTrigrams++;
543                    Trigramscore += 0.0 - inputTriGrams[g] / sumTrigrams;
544                }
545                else if (!inputTriGrams.ContainsKey(g))
546                {
547                    sumTrigrams++;
548                    Trigramscore += corpusTrigrams[g][1];
549                }
550            }
551            double total = beta * bigramscore + gamma * Trigramscore;
552            if (total != 0.0)
553            {
554                GuiLogMessage(total.ToString(), NotificationLevel.Debug);
555            }
556            return total;
557            */
558        }//end Execute
559
560        public double regex(string input)
561        {
562            if (settings.RegEx == null)
563            {
564                GuiLogMessage("There is no Regular Expression to be searched for. Please insert regex in the 'Regular Expression' - Textarea", NotificationLevel.Error);
565                return new Double();
566            }
567            try
568            {
569                Match match = Regex.Match(input, settings.RegEx);
570                if (match.Success)
571                {
572                    return 1.0;
573                }
574                else
575                {
576                    return -1.0;
577                }
578            }
579            catch (Exception e)
580            {
581                GuiLogMessage(e.Message, NotificationLevel.Error);
582                return -1.0;
583            }
584
585        }
586
587
588        /// <summary>
589        /// Calculates the Index of Coincidence multiplied with 100 of
590        /// a given byte array
591        ///
592        /// for example a German text has about 7.62
593        ///           an English text has about 6.61
594        /// </summary>
595        /// <param name="text">text to use</param>
596        /// <returns>Index of Coincidence</returns>
597        public double calculateIndexOfCoincidence(byte[] text)
598        {
599            return calculateIndexOfCoincidence(text, text.Length);
600        }
601
602        /// <summary>
603        /// Calculates the Index of Coincidence multiplied with 100 of
604        /// a given byte array
605        ///
606        /// for example a German text has about 7.62
607        ///           an English text has about 6.61
608        /// </summary>
609        /// <param name="text">text to use</param>
610        /// <param name="text">bytesToUse</param>
611        /// <returns>Index of Coincidence</returns>
612        public double calculateIndexOfCoincidence(byte[] text, int bytesToUse)
613        {
614            if (bytesToUse > text.Length)
615                bytesToUse = text.Length;
616
617            double[] n = new double[256];
618            //count all ASCII symbols
619            int counter = 0;
620            foreach (byte b in text)
621            {
622                n[b]++;
623                counter++;
624                if (counter == bytesToUse)
625                    break;
626            }
627
628            double coindex = 0;
629            //sum them
630            for (int i = 0; i < n.Length; i++)
631            {
632                coindex = coindex + n[i] * (n[i] - 1);
633            }
634
635            coindex = coindex / (bytesToUse);
636            coindex = coindex / (bytesToUse - 1);
637
638            return coindex * 100;
639
640        }//end calculateIndexOfCoincidence
641
642
643        private int lastUsedSize = -1;
644        private double[] xlogx;
645        private Mutex prepareMutex = new Mutex();
646
647        private void prepareEntropy(int size)
648        {
649            xlogx = new double[size + 1];
650            //precomputations for fast entropy calculation     
651            xlogx[0] = 0.0;
652            for (int i = 1; i <= size; i++)
653                xlogx[i] = -1.0 * i * Math.Log(i / (double)size) / Math.Log(2.0);
654        }
655
656        /// <summary>
657        /// Calculates the Entropy of a given byte array
658        /// for example a German text has about 4.0629
659        /// </summary>
660        /// <param name="text">text to use</param>
661        /// <returns>Entropy</returns>
662        public double calculateEntropy(byte[] text)
663        {
664            return calculateEntropy(text, text.Length);
665        }
666
667        /// <summary>
668        /// Calculates the Entropy of a given byte array
669        /// for example a German text has about 4.0629
670        /// </summary>
671        /// <param name="text">text to use</param>
672        /// <returns>Entropy</returns>
673        public double calculateEntropy(byte[] text, int bytesToUse)
674        {
675            return NativeCryptography.Crypto.calculateEntropy(text, bytesToUse);
676            if (bytesToUse > text.Length)
677           
678                bytesToUse = text.Length;
679           
680            if (lastUsedSize != bytesToUse)
681            {
682                try
683                {
684                    prepareMutex.WaitOne();
685                    if (lastUsedSize != bytesToUse)
686                    {
687                        prepareEntropy(bytesToUse);
688                        lastUsedSize = bytesToUse;
689                    }
690                }
691                finally
692                {
693                    prepareMutex.ReleaseMutex();
694                }
695            }
696
697            int[] n = new int[256];
698            //count all ASCII symbols
699            for (int counter = 0; counter < bytesToUse; counter++)
700            {
701                n[text[counter]]++;
702            }
703
704            double entropy = 0;
705            //calculate probabilities and sum entropy
706            for (int i = 0; i < 256; i++)
707                entropy += xlogx[n[i]];
708
709            return entropy / (double)bytesToUse;
710
711        }//end calculateEntropy
712
713        /// <summary>
714        /// This method calculates a trigram log2 score of a given text on the basis of a given grams dictionary.
715        /// Case is insensitive.
716        /// </summary>
717        /// <param name="input">The text to be scored</param>
718        /// <param name="length">n-gram length</param>
719        /// <returns>The trigram score result</returns>
720        public double calculateNGrams(string input, int length, int valueSelection, bool weighted)
721        {
722
723            this.statistics = new Dictionary<int, IDictionary<string, double[]>>();
724            double score = 0;
725            if (corpusBigrams == null && length == 2)
726            { corpusBigrams = GetStatistics(length); }
727
728            if (corpusTrigrams == null && length == 3)
729            { corpusTrigrams = GetStatistics(length); }
730            input = input.ToUpper();
731            // FIXME: case handling?
732
733            HashSet<string> inputGrams = new HashSet<string>();
734
735            foreach (string g in GramTokenizer.tokenize(input, length, false))
736            {
737                // ensure each n-gram is counted only once
738                if (inputGrams.Add(g))
739                {
740                    if (corpusBigrams.ContainsKey(g) && length == 2 )
741                    {
742                        score += corpusBigrams[g][valueSelection];
743                        if (weighted) { weights(g, 2); }
744                    }
745                    if (length == 3 )
746                    {
747                        if (corpusTrigrams.ContainsKey(g))
748                        {
749                            score += corpusTrigrams[g][valueSelection];
750                            if (weighted) { weights(g, 3); }
751                        }
752                    }
753                }
754            }
755
756            return score;
757        }
758        public IDictionary<string, double[]> GetStatistics(int gramLength)
759        {
760            // FIXME: inputTriGrams is not being used!
761
762            // FIXME: implement exception handling
763            if (!statistics.ContainsKey(gramLength))
764            {
765                //GuiLogMessage("Trying to load default statistics for " + gramLength + "-grams", NotificationLevel.Info);
766                statistics[gramLength] = LoadDefaultStatistics(gramLength);
767            }
768
769            return statistics[gramLength];
770        }
771
772        private IDictionary<string, double[]> LoadDefaultStatistics(int length)
773        {
774           
775            txtList = dataMgr.LoadDirectory(DATATYPE);
776           
777            switch (this.settings.StatisticsCorpus)
778            {
779                case 0:
780                    return calculateAbsolutes(txtList["statisticscorpusde"].DataFile.FullName, length);
781                   
782                case 1:
783                    return calculateAbsolutes(txtList["statisticscorpusen"].DataFile.FullName, length);
784                case 2:
785                    return calculateAbsolutes(this.settings.customFilePath, length);
786                //to prevent a poss. initial-err
787                //default:
788                //    return calculateAbsolutes(txtList["statisticscorpusen"].DataFile.FullName, length);
789
790            }
791            return calculateAbsolutes(txtList["statisticscorpusde"].DataFile.FullName, length); //default
792           
793        }
794
795        private IDictionary<string, double[]> calculateAbsolutes(String path, int length)
796        {
797
798
799            Dictionary<string, double[]> grams = new Dictionary<string, double[]>();
800            int checkLength;
801            StreamReader reader = new StreamReader(path);
802            String text = reader.ReadToEnd();
803
804            text.ToUpper();
805            text = Regex.Replace(text, "[^A-Z]*", "");
806
807            if (length == 2)
808            {
809                checkLength = text.Length - 1;
810            }
811            else
812            {
813                checkLength = text.Length - 2;
814            }
815            for (int i = 0; i < checkLength; i++)
816            {
817                char a = text[i];
818                char b = text[i + 1];
819                String key;
820                if (length == 3) // Trigrams
821                {
822                    char c = text[i + 2];
823                    key = a.ToString();
824                    key = key + b.ToString();
825                    key = key + c.ToString();
826                }
827                else // Bigrams
828                {
829                    key = a.ToString();
830                    key = key + b.ToString();
831                }
832
833                if (!grams.ContainsKey(key))
834                {
835                    grams.Add(key, new double[] { 1, 0, 0, 0}); 
836                }
837                else
838                {
839                    grams[key][0] = grams[key][0] + 1.0;
840                }
841            }
842
843            double sum = grams.Values.Sum(item => item[ABSOLUTE]);
844            GuiLogMessage("Sum of all n-gram counts is: " + sum, NotificationLevel.Debug);
845
846            // calculate scaled values
847            foreach (double[] g in grams.Values)
848            {
849                g[PERCENTAGED] = g[ABSOLUTE] / sum;
850                g[LOG2] = Math.Log(g[ABSOLUTE], 2);
851                g[SINKOV] = Math.Log(g[PERCENTAGED], Math.E);
852            }
853
854
855
856            return grams;
857        }
858
859        public string ByteArrayToString(byte[] arr)
860        {
861            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
862            return enc.GetString(arr);
863        }
864
865
866        #endregion
867
868
869    }
870
871    #region slave
872
873    public class CostFunctionControl : IControlCost
874    {
875        public event IControlStatusChangedEventHandler OnStatusChanged;
876        #region IControlCost Members
877
878        private CostFunction plugin;
879
880        #endregion
881
882        /// <summary>
883        /// Constructor
884        /// </summary>
885        /// <param name="plugin"></param>
886        public CostFunctionControl(CostFunction plugin)
887        {
888            this.plugin = plugin;
889        }
890
891        public int getBytesToUse()
892        {
893            try
894            {
895                return int.Parse(((CostFunctionSettings)this.plugin.Settings).BytesToUse);
896            }
897            catch (Exception ex)
898            {
899                throw new Exception("Entered bytesToUse is not an integer: " + ex.Message);
900            }
901        }
902
903        /// <summary>
904        /// Returns the relation operator of the cost function which is set by by CostFunctionSettings
905        /// </summary>
906        /// <returns>RelationOperator</returns>
907        public RelationOperator getRelationOperator()
908        {
909            switch (((CostFunctionSettings)this.plugin.Settings).FunctionType)
910            {
911                case 0: //Index of coincidence
912                    return RelationOperator.LargerThen;
913                case 1: //Entropy
914                    return RelationOperator.LessThen;
915                case 2: // Bigrams: log 2
916                    return RelationOperator.LessThen;
917                case 3: // Sinkov
918                    return RelationOperator.LargerThen;
919                case 4: // percentage
920                    return RelationOperator.LargerThen;
921                case 5: // Regular Expression
922                    return RelationOperator.LargerThen;
923                case 6: // Weighted Bigrams/Trigrams
924                    return RelationOperator.LargerThen;
925
926                default:
927                    throw new NotImplementedException("The value " + ((CostFunctionSettings)this.plugin.Settings).FunctionType + " is not implemented.");
928            }//end switch
929        }//end getRelationOperator
930
931        /// <summary>
932        /// Calculates the cost function of the given text
933        ///
934        /// Cost function can be set by CostFunctionSettings
935        /// This algorithm uses a bytesToUse which can be set by CostFunctionSettings
936        /// If bytesToUse is set to 0 it uses the whole text
937        ///
938        /// </summary>
939        /// <param name="text"></param>
940        /// <returns>cost</returns>
941        public double calculateCost(byte[] text)
942        {
943            int bytesToUse = 0;
944            try
945            {
946                bytesToUse = ((CostFunctionSettings)this.plugin.Settings).BytesToUseInteger;
947            }
948            catch (Exception ex)
949            {
950                throw new Exception("Entered bytesToUse is not an integer: " + ex.Message);
951            }
952
953            switch (((CostFunctionSettings)this.plugin.Settings).FunctionType)
954            {
955                case 0: //Index of coincidence
956                    return plugin.calculateIndexOfCoincidence(text, bytesToUse);
957                case 1: //Entropy
958                    return plugin.calculateEntropy(text, bytesToUse);
959                case 2: // Bigrams: log 2
960                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 2, false);
961                case 3: // Bigrams: Sinkov
962                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 3, false);
963                case 4: // Bigrams: Percentaged
964                    return plugin.calculateNGrams(plugin.ByteArrayToString(text), 2, 1, false);
965                case 5: // regular expression
966                    return plugin.regex(plugin.ByteArrayToString(text));
967                case 6:
968                    return plugin.calculateWeighted(plugin.ByteArrayToString(text));
969                default:
970                    throw new NotImplementedException("The value " + ((CostFunctionSettings)this.plugin.Settings).FunctionType + " is not implemented.");
971            }//end switch
972        }
973
974
975    #endregion
976    }
977
978}
979
Note: See TracBrowser for help on using the repository browser.