-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds flight optimizer/scorer and montecarlo.
adds the flight optimizer and scorer interfaces. the first returns the score and distance for a given flight, allowing multiple implementations of the optimization algorithm (montecarlo, simulated annealing, genetic, branch/bound, ...). actual implementation based on montecarlo is included. the second is the actual scoring interface, which takes a set of turn points and returns the score points for the competition (netcoupe, online contest, ...). netcoupe scoring implementation is included. Fixes #48, #85.
- Loading branch information
1 parent
8be8388
commit bed55c5
Showing
15 changed files
with
33,574 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright 2015 The ezgliding Authors. | ||
// | ||
// This file is part of ezgliding. | ||
// | ||
// ezgliding is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// ezgliding is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with ezgliding. If not, see <http://www.gnu.org/licenses/>. | ||
// | ||
// Author: Ricardo Rocha <rocha.porto@gmail.com> | ||
|
||
package flight | ||
|
||
import ( | ||
"fmt" | ||
"math/rand" | ||
|
||
"github.com/rochaporto/ezgliding/spatial" | ||
) | ||
|
||
// Montecarlo is the montecarlo based implementation of the flight Optimizer. | ||
type Montecarlo struct { | ||
Cycles int | ||
MCCycles int | ||
MCGuesses int | ||
} | ||
|
||
// NewMontecarlo returns a new Montecarlo optimizer instance. | ||
func NewMontecarlo() *Montecarlo { | ||
return &Montecarlo{Cycles: 10, MCCycles: 100000, MCGuesses: 0} | ||
} | ||
|
||
// Optimize implements Optimizer(). | ||
func (mc *Montecarlo) Optimize(track []Point, nTP int, scorer Scorer) (OptResult, error) { | ||
maxDistChan := make(chan float64, mc.Cycles) | ||
maxChan := make(chan []int, mc.Cycles) | ||
|
||
for c := 0; c < mc.Cycles; c++ { | ||
go func() { | ||
var candidate = make([]int, nTP) | ||
var max = make([]int, nTP) | ||
var cdistance float64 | ||
var maxDistance = 0.0 | ||
|
||
// start with uniform distribution (equal distance) | ||
for i := 0; i < nTP; i++ { | ||
candidate[i] = (len(track) / (nTP - 1)) * i | ||
} | ||
cdistance = mc.distance(track, candidate) | ||
|
||
// run montecarlo cycles | ||
var index, bwp, twp, nwp int | ||
for i := 0; i < mc.MCCycles; i++ { | ||
index = rand.Intn(nTP-2) + 1 | ||
bwp = candidate[0] | ||
if index > 0 { | ||
bwp = candidate[index-1] | ||
} | ||
twp = len(track) - 1 | ||
if index < nTP-1 { | ||
twp = candidate[index+1] | ||
} | ||
nwp = rand.Intn(twp-bwp) + bwp | ||
candidate[index] = nwp | ||
//sort.Sort(sort.IntSlice(candidate)) | ||
cdistance = mc.distance(track, candidate) | ||
if cdistance > maxDistance { | ||
maxDistance = cdistance | ||
max = candidate | ||
} | ||
} | ||
|
||
maxDistChan <- maxDistance | ||
maxChan <- max | ||
}() | ||
} | ||
|
||
gMax := make([]int, nTP) | ||
gMaxDistance := 0.0 | ||
var dist float64 | ||
var pts = make([]int, nTP) | ||
for i := 0; i < mc.Cycles; i++ { | ||
dist = <-maxDistChan | ||
pts = <-maxChan | ||
if dist > gMaxDistance { | ||
gMaxDistance = dist | ||
gMax = pts | ||
} | ||
} | ||
fmt.Printf("%v :: %v\n", gMax, len(track)) | ||
result := OptResult{TurnPoints: make([]Point, nTP), Distance: gMaxDistance} | ||
for i := 0; i < nTP; i++ { | ||
result.TurnPoints[i] = track[gMax[i]] | ||
} | ||
return result, nil | ||
} | ||
|
||
func (mc *Montecarlo) distance(track []Point, tps []int) float64 { | ||
distance := 0.0 | ||
for i := 0; i < len(tps)-1; i++ { | ||
v := spatial.GCDistance(track[tps[i]].Latitude, track[tps[i]].Longitude, | ||
track[tps[i+1]].Latitude, track[tps[i+1]].Longitude) | ||
distance += v | ||
} | ||
return distance | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright 2015 The ezgliding Authors. | ||
// | ||
// This file is part of ezgliding. | ||
// | ||
// ezgliding is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// ezgliding is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with ezgliding. If not, see <http://www.gnu.org/licenses/>. | ||
// | ||
// Author: Ricardo Rocha <rocha.porto@gmail.com> | ||
|
||
package flight | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
type MontecarloTest struct { | ||
t string | ||
loc string | ||
res Result | ||
} | ||
|
||
var montecarloTests = []MontecarloTest{ | ||
MontecarloTest{t: "sample flight", loc: "./t/sample-flight.igc", res: Result{Distance: 710000.0}}, | ||
MontecarloTest{t: "sample flight2", loc: "./t/sample-flight2.igc", res: Result{Distance: 710000.0}}, | ||
} | ||
|
||
func TestMontecarlo(t *testing.T) { | ||
mc := NewMontecarlo() | ||
for _, test := range montecarloTests { | ||
content, err := fetch(test.loc) | ||
if err != nil { | ||
t.Errorf("failed to load flight :: %v", err) | ||
continue | ||
} | ||
f, err := ParseIGC(content) | ||
if err != nil { | ||
t.Errorf("failed to parse content :: %v", err) | ||
continue | ||
} | ||
result, err := mc.Optimize(f.Points) | ||
if err != nil { | ||
t.Errorf("failed montecarlo optimize :: %v", err) | ||
continue | ||
} | ||
fmt.Printf("%v\n%v\n", test.t, result.Distance) | ||
for i, p := range result.TurnPoints { | ||
fmt.Printf("data.setCell(%v, 0, %v);\n", i, p.Latitude) | ||
fmt.Printf("data.setCell(%v, 1, %v);\n", i, p.Longitude) | ||
fmt.Printf("data.setCell(%v, 2, 'WP%v');\n", i, i) | ||
} | ||
} | ||
} | ||
|
||
// FIXME: should be a common function in another package | ||
func fetch(location string) (string, error) { | ||
var content []byte | ||
// case http | ||
resp, err := http.Get(location) | ||
if err == nil { | ||
defer resp.Body.Close() | ||
content, err = ioutil.ReadAll(resp.Body) | ||
} else { // case file | ||
resp, err := ioutil.ReadFile(location) | ||
if err != nil { | ||
return "", err | ||
} | ||
content = resp | ||
} | ||
return string(content), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2015 The ezgliding Authors. | ||
// | ||
// This file is part of ezgliding. | ||
// | ||
// ezgliding is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// ezgliding is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with ezgliding. If not, see <http://www.gnu.org/licenses/>. | ||
// | ||
// Author: Ricardo Rocha <rocha.porto@gmail.com> | ||
|
||
package flight | ||
|
||
// Optimizer returns the optimized distance and score for the given track. | ||
// nTP is the number of turnpoints to optimize for, and includes start and | ||
// finish. This means 3 for out and return, 4 for triangle, ... | ||
// The optimizer implementation will evaluation most or all combinations | ||
// of track points building a set of valid TPs, and pass that to the scorer. | ||
// The set of TPs with the higher score is returned, along with the actual | ||
// distance between TPs. | ||
type Optimizer interface { | ||
Optimize(track []Point, nTP int, scorer Scorer) (OptResult, error) | ||
} | ||
|
||
// OptResult holds information about a given flight optimization. | ||
type OptResult struct { | ||
// TurnPoints is the set of turn points in this optimization. | ||
TurnPoints []Point | ||
// Distance is the total distance between turnpoints (direct line). | ||
Distance float64 | ||
// Score is the number of points given by the Scorer implementation. | ||
Score float64 | ||
// Description is a given task description by the Scorer implementation. | ||
ScorerID string | ||
} | ||
|
||
// Optimizers holds a map of all available Optimizers, keyed on ID. | ||
var Optimizers = map[string]Optimizer{ | ||
"montecarlo": Optimizer(NewMontecarlo()), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright 2015 The ezgliding Authors. | ||
// | ||
// This file is part of ezgliding. | ||
// | ||
// ezgliding is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// ezgliding is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with ezgliding. If not, see <http://www.gnu.org/licenses/>. | ||
// | ||
// Author: Ricardo Rocha <rocha.porto@gmail.com> | ||
|
||
package flight | ||
|
||
// Scorer returns the score for the given set of turn points. | ||
// The number of turn points given is variable and the resulting score will | ||
// depend on it. As an example, the netcoupe scorer will take any of 1, 2 or | ||
// 3 turn points (but not more), and for 2TP (triangle) will give a higher | ||
// score if it is an FAI triangle (for the same total distance between TPs). | ||
type Scorer interface { | ||
Score(turnPoints []Point) (float64, error) | ||
} |
Oops, something went wrong.