ftsrg / trainbenchmark-ttc

(Deprecated.) Framework for the TTC 2015 Train Benchmark case
Eclipse Public License 1.0
1 stars 8 forks source link

[NMF] Correctness of the solution #16

Open tsdh opened 9 years ago

tsdh commented 9 years ago

Hi @georghinkel,

I think the NMF solution is not correct. In the output the transformation prints the rss values should be the number of matches. When I run the NMF solution with the SemaphoreNeighbor query on the model of size 1, the first check finds 94 matches with both the incremental and the batch version. The correct number of matches is just 1.

Same with model 2: NMF finds again 94 matches, the correct number is 5.

And with model 4: NMF initially finds 409 matches whereas the correct number is 10. And then it's getting stranger. In the first re-check, it finds only 1 match (which would mean it repaired more than the 10 matches [this is the fixed strategy]). In the second re-check, it finds again 314 matches. Well, then 1 again, then 314 again, etc.

Model 8: NMF finds 996 initial matches, the correct number is 15. And during the re-checks, the numbers are 275, 164, 4, 898, 4, 898, 4, 898, 155, 164.

Well, there seems to be something pretty wrong. It always finds way too many matches, it repairs not just 10 in the fixed strategy, and how on earth can it be that the number of matches increases again after repairing elements?

tsdh commented 9 years ago

Now I've tried the RouteSensor query, and there NMF doesn't find any match in the models 1, 2, 4, and 8. Eventually, in the 16 model, it finds twelve matches. The correct numbers would be 7, 8, 15, 28, 58.

The PosLength, SwitchSet, and SwitchSensor queries seem to be correct. At least the number of matches are the same as with the reference java solution, and always 10 are fixed when using the fixed changeset.

georghinkel commented 9 years ago

Hi Tassilo,

you are right. There is a small bug in the pattern that of course affects both the incremental and the batch version as both of them use the same pattern: I must have overread the clause that route1 != route2. Now, it does not find any match, anymore :)

The reason for this, as well as for the RouteSensor pattern is that both patterns use the rc.Routes property. Thus, they only consider routes that are contained directly in the railway container. I exchanged rc.Routes with rc.Descendants.OfType and get the expected results.

However, Descendents() is a very expensive operation in NMF, so this degrades the performance a bit. I will update the repository and the SHARE demo. Maybe I find a better solution than querying Descendents().

Georg

georghinkel commented 9 years ago

The fact that route1 == route2 was allowed in the SemaphoreNeighbor query also leads to the rather strange behavior that you mentioned. The problem is that many many more than just 10 matches will be repaired if route2.Entry = route1.Exit. If route1 == route2, this yields a match for each and every track element in this route. All of them are "repaired" by setting the entry of this route to its exit. I still don't know why it was alternating, but I will investigate.

The current patterns that I am using now are the following:

        if (task == "RouteSensor")
        {
            // RouteSensor
            Fix(pattern: from route in rc.Descendants().OfType<Route>()
                         from swP in route.Follows.OfType<SwitchPosition>()
                         where swP.Switch.Sensor != null && !route.DefinedBy.Contains(swP.Switch.Sensor)
                         select new { Route = route, Sensor = swP.Switch.Sensor, SwitchPos = swP },
                 action: match => match.Route.DefinedBy.Add(match.Sensor),
                 sortKey: match => string.Format("<route : {0:0000}, sensor : {1:0000}, swP : {2:0000}, sw : {3:0000}>",
                     match.Route.Id.GetValueOrDefault(),
                     match.Sensor.Id.GetValueOrDefault(),
                     match.SwitchPos.Id.GetValueOrDefault(),
                     match.SwitchPos.Switch.Id.GetValueOrDefault()));
        }
        if (task == "SemaphoreNeighbor")
        {
            // SemaphoreNeighbor
            Fix(pattern: from route1 in rc.Descendants().OfType<Route>()
                         from route2 in rc.Descendants().OfType<Route>()
                         where route1 != route2 && route2.Entry != route1.Exit
                         from sensor1 in route1.DefinedBy
                         from te1 in sensor1.Elements
                         from te2 in te1.ConnectsTo
                         where te2.Sensor != null && route2.DefinedBy.Contains(te2.Sensor)
                         select new { Route1 = route1, Route2 = route2, Te1 = te1, Te2 = te2 },
                action: match => match.Route2.Entry = match.Route1.Exit,
                sortKey: match => string.Format("<semaphore : {0:0000}, route1 : {1:0000}, route2 : {2:0000}, sensor1 : {3:0000}, sensor2 : {4:0000}, te1 : {5:0000}, te2 : {6:0000}>",
                    match.Route1.Exit.Id.GetValueOrDefault(),
                    match.Route1.Id.GetValueOrDefault(),
                    match.Route2.Id.GetValueOrDefault(),
                    match.Te1.Sensor.Id.GetValueOrDefault(),
                    match.Te2.Sensor != null ?
                        match.Te2.Sensor.Id.GetValueOrDefault() : 0,
                    match.Te1.Id.GetValueOrDefault(),
                    match.Te2.Id.GetValueOrDefault()));
        }
tsdh commented 9 years ago

Ok, thanks.