Ejemplo n.º 1
0
        static void Main(string[] args)
        {
            var           random = new Random(3_14159265);
            Func <double> vertexAttributeGenerator = () =>
            {
                return(random.NextDouble());
            };
            Func <double> edgeAttributeGenerator = () =>
            {
                return(random.NextDouble());
            };

            double vertexBound = 2;
            double edgeBound   = 3;
            double vertexDecay = 1;
            double edgeDecay   = 1;

            Func <double, double, double, double> boundMetric = (a, bound, decay) => bound * a / (1 / decay + a);

            Func <double, double, double> vertexRelabel = (a1, a2) =>
            {
                return(boundMetric(Math.Abs(a1 - a2), vertexBound, vertexDecay));
            };
            Func <double, double> vertexAdd    = a => boundMetric(Math.Abs(a), vertexBound, vertexDecay);
            Func <double, double> vertexRemove = vertexAdd;

            Func <double, double, double> edgeRelabel = (a1, a2) =>
            {
                return(boundMetric(Math.Abs(a1 - a2), edgeBound, edgeDecay));
            };
            Func <double, double> edgeAdd    = a => boundMetric(Math.Abs(a), edgeBound, edgeDecay);
            Func <double, double> edgeRemove = edgeAdd;



            // Func<double, double, double> vertexRelabel = (a1, a2) =>
            // {
            //     return Math.Abs(a1 - a2);
            // };
            // Func<double, double> vertexAdd = a => Math.Abs(a);
            // Func<double, double> vertexRemove = vertexAdd;

            // Func<double, double, double> edgeRelabel = (a1, a2) =>
            // {
            //     return Math.Abs(a1 - a2);
            // };
            // Func<double, double> edgeAdd = a => Math.Abs(a);
            // Func<double, double> edgeRemove = edgeAdd;

            var a = new List <double>()
            {
                0, 1, .5, 1d / 3, 2d / 3, -1, 2, 10, -10, 100, -100, 1000, -1000
            };
            var b = new List <double>()
            {
                0, 1, .5, 1d / 3, 2d / 3, -1, 2, 10, -10, 100, -100, 1000, -1000
            };
            var RiesenBunke2009AB = (1, 1);



            for (int gVertices = 8; gVertices < 12; gVertices++)
            {
                var hVertices = gVertices;
                // for (int hVertices = gVertices; hVertices > 0; hVertices-=1)
                {
                    var measurements = 0;
                    var results      = new Dictionary <(double, double), double>();
                    foreach (var aElement in a)
                    {
                        foreach (var bElement in b)
                        {
                            results.Add((aElement, bElement), 0);
                        }
                    }
                    for (double gDensity = 1.0; gDensity > 0; gDensity -= 0.1)
                    {
                        for (double hDensity = gDensity; hDensity > 0; hDensity -= 0.1)
                        {
                            for (int iter = 0; iter < 5; iter++)
                            {
                                var G = RandomGraphFactory.GenerateRandomInstance(
                                    vertices: gVertices,
                                    density: gDensity,
                                    directed: true,
                                    vertexAttributeGenerator: vertexAttributeGenerator,
                                    edgeAttributeGenerator: edgeAttributeGenerator
                                    );
                                var H = RandomGraphFactory.GenerateRandomInstance(
                                    vertices: hVertices,
                                    density: hDensity,
                                    directed: true,
                                    vertexAttributeGenerator: vertexAttributeGenerator,
                                    edgeAttributeGenerator: edgeAttributeGenerator
                                    );

                                var matchingParameters = new GraphMatchingParameters <int, double, double>
                                {
                                    aCollection    = a,
                                    bCollection    = b,
                                    edgeAdd        = edgeAdd,
                                    vertexAdd      = vertexAdd,
                                    edgeRelabel    = edgeRelabel,
                                    edgeRemove     = edgeRemove,
                                    vertexRemove   = vertexRemove,
                                    vertexRelabel  = vertexRelabel,
                                    encodingMethod = GraphEncodingMethod.Wojciechowski
                                };
                                var matching = new VertexPartialMatchingNode <int, double, double>(
                                    G,
                                    H,
                                    matchingParameters
                                    );

                                var myRelativeError    = (matching.BestUpperBound - matching.BestLowerBound) / matching.BestLowerBound;
                                var theirRelativeError = (matching.BestUpperBound - matching.abLowerBounds[RiesenBunke2009AB]) / matching.abLowerBounds[RiesenBunke2009AB];
                                var eps = 1e-12;
                                // if (theirRelativeError > eps)
                                // {
                                //     System.Console.WriteLine($"|Vg|={gVertices}, |Eg|={gDensity:f2}, |Vh|={hVertices}, |Eh|={hDensity:f2}. My estimate / theirs {matching.LowerBound / matching.abLowerBounds[RiesenBunke2009AB]:f2}.");

                                // }

                                // var theirLowerBound = matching.abLowerBounds[(2d/3, .5)];
                                // if (theirLowerBound > eps)
                                {
                                    measurements += 1;
                                    foreach (var kvp in matching.abLowerBounds)
                                    {
                                        // var score = (matching.UpperBound - kvp.Value) / matching.UpperBound;
                                        var score = kvp.Value > Math.Max(Math.Max(
                                                                             matching.abLowerBounds[(.5, .5)],
        static void Main(string[] args)
        {
            using var context = new EnronContext();
            Console.WriteLine($"{context.Emails.Count()} emails in total.");

            // var resultsFilePath = "./results.txt";
            var topResultsFilePath    = "./top_results.txt";
            var topTopResultsFilePath = "./top_top_results.txt";

            var matchingFeatureSelectors = new List <(string, Func <VertexPartialMatchingNode <string, double, double>, double>)>()
            {
                ("Upper bound", matching => matching.BestUpperBound),
                ("Lower bound", matching => matching.BestLowerBound)
            };

            var edgeCostTypes = new List <(string, CostType, List <double>, List <double>)>()
            {
                // ("Unit cost Wojciechowski .5", CostType.UnitCost, new List<double>(){.5}, new List<double>(){.5}),
                // ("Unit cost Wojciechowski (1.) .5", CostType.UnitCost, new List<double>(){1}, new List<double>(){.5}),
                // ("Unit cost Wojciechowski .5 Riesen Bunke 1.", CostType.UnitCost, new List<double>(){.5, 1}, new List<double>(){1, .5}),
                // ("Unit cost Riesen Bunke 1.", CostType.UnitCost, new List<double>(){1}, new List<double>(){1}),

                ("Absolute value Wojciechowski .5", CostType.AbsoluteValue, new List <double>()
                {
                    .5
                }, new List <double>()
                {
                    .5
                }),
                // ("Absolute value Wojciechowski (1.) .5", CostType.AbsoluteValue, new List<double>(){1}, new List<double>(){.5}),
                // ("Absolute value Wojciechowski .5 Riesen Bunke 1.", CostType.AbsoluteValue, new List<double>(){.5, 1}, new List<double>(){1, .5}),
                ("Absolute value Riesen Bunke 1.", CostType.AbsoluteValue, new List <double>()
                {
                    1
                }, new List <double>()
                {
                    1
                }),

                // ("Absolute value bounded Wojciechowski .5", CostType.AbsoluteValueBounded, new List<double>(){.5}, new List<double>(){.5}),
                // ("Absolute value bounded Wojciechowski (1.) .5", CostType.AbsoluteValueBounded, new List<double>(){1}, new List<double>(){.5}),
                // ("Absolute value bounded Wojciechowski .5 Riesen Bunke 1.", CostType.AbsoluteValueBounded, new List<double>(){.5, 1}, new List<double>(){1, .5}),
                // ("Absolute value bounded Riesen Bunke 1.", CostType.AbsoluteValueBounded, new List<double>(){1}, new List<double>(){1}),
            };

            var results    = new Dictionary <(int vertexUpperBound, int k, string distanceScorerName, string edgeCostType, string matchingFeatureSelectorName), (double testAccuracy, double validationAccuracy)>();
            var topResults = new Dictionary <(int vertexUpperBound, int k, string distanceScorerName, string edgeCostType, string matchingFeatureSelectorName), (double testAccuracy, double validationAccuracy)>();

            for (int iteration = 0; iteration < 10; iteration++)
            {
                for (int vertexUpperBound = 3; vertexUpperBound < 8; vertexUpperBound++)
                {
                    var dataset = GenerateDataSet(
                        context,
                        trainingProportion: 8,
                        validatingProportion: 1,
                        testingProportion: 1,
                        vertexUpperBound: vertexUpperBound,
                        randomSeed: iteration
                        );
                    foreach (var(matchingFeatureSelectorName, matchingFeatureSelector) in matchingFeatureSelectors)
                    {
                        foreach (var(edgeCostTypeName, edgeCostType, aCollection, bCollection) in edgeCostTypes)
                        {
                            var matchingParameters = GraphMatchingParameters <string, double, double> .DoubleCostComposer(
                                CostType.UnitCost,
                                edgeCostType
                                );

                            matchingParameters.aCollection = aCollection;
                            matchingParameters.bCollection = bCollection;

                            // determine closest neighbours for each test and validation graph
                            var testMatchingClassPairsList       = new List <(List <(VertexPartialMatchingNode <string, double, double>, bool)>, bool)>();
                            var validationMatchingClassPairsList = new List <(List <(VertexPartialMatchingNode <string, double, double>, bool)>, bool)>();

                            foreach (var(pair, i) in dataset.testSet.Zip(Enumerable.Range(0, int.MaxValue)))
                            {
                                var pairToAdd = (
                                    KNNClassifier.KNNClassifier.FindClosest(pair.Item1, dataset.trainingSet, matchingParameters, matchingFeatureSelector),
                                    pair.Item2
                                    );
                                testMatchingClassPairsList.Add(pairToAdd);
                                // System.Console.WriteLine($"Test set: computed distance: {i * 100d / dataset.testSet.Count:f2}%.");
                            }

                            foreach (var(pair, i) in dataset.validationSet.Zip(Enumerable.Range(0, int.MaxValue)))
                            {
                                var pairToAdd = (
                                    KNNClassifier.KNNClassifier.FindClosest(pair.Item1, dataset.trainingSet, matchingParameters, matchingFeatureSelector),
                                    pair.Item2
                                    );
                                validationMatchingClassPairsList.Add(pairToAdd);
                                // System.Console.WriteLine($"Validation set: computed distance: {i * 100d / dataset.validationSet.Count:f2}%.");
                            }

                            Func <int, Func <int, VertexPartialMatchingNode <string, double, double>, double>, List <(List <(VertexPartialMatchingNode <string, double, double>, bool)>, bool)>, double> getAccuracy = (k, distanceScorer, matchingClassPairsList) =>
                            {
                                var truePositives  = 0;
                                var falsePositives = 0;
                                var trueNegatives  = 0;
                                var falseNegatives = 0;

                                foreach (var(matchingClassPairs, testGraphLabel) in matchingClassPairsList)
                                {
                                    var classificationResult = KNNClassifier.KNNClassifier.Classify <string, double, double, bool>(
                                        matchingClassPairs,
                                        distanceScorer,
                                        k: k
                                        );

                                    var result = (expected : testGraphLabel, received : classificationResult.graphClass);
                                    if (result.expected)
                                    {
                                        if (result.received)
                                        {
                                            truePositives += 1;
                                        }
                                        else
                                        {
                                            falseNegatives += 1;
                                        }
                                    }
                                    else
                                    {
                                        if (result.received)
                                        {
                                            falsePositives += 1;
                                        }
                                        else
                                        {
                                            trueNegatives += 1;
                                        }
                                    }
                                }

                                return((truePositives + trueNegatives) * 1d / matchingClassPairsList.Count);
                            };

                            var ks = new int[]
                            {
                                1,
                                2,
                                3,
                                4,
                                5,
                                6,
                                7,
                                8,
                                9,
                                10,
                                -1
                            };

                            var distanceScorers = new (string, Func <int, VertexPartialMatchingNode <string, double, double>, double>)[]