Archived
0

fix scorer

This commit is contained in:
iMoHax
2015-05-22 17:33:07 +03:00
parent a549dce54a
commit 970806d278
13 changed files with 206 additions and 45 deletions

View File

@@ -10,11 +10,10 @@ import java.util.List;
public class RouteEntry {
private final Vendor vendor;
private final double fuel;
private final double score;
private final List<Order> orders;
private boolean land;
private boolean refill;
private double score;
public RouteEntry(Vendor vendor, boolean refill, double fuel, double score) {
orders = new ArrayList<>();
@@ -48,6 +47,10 @@ public class RouteEntry {
return score;
}
void setScore(double score) {
this.score = score;
}
public void add(Order order){
orders.add(order);
}

View File

@@ -178,6 +178,8 @@ public class RouteFiller {
if (best != TRANSIT)
entry.addAll(best.bestOrders);
}
int jumps = i==0 || entries.get(i-1).getVendor().getPlace().equals(entry.getVendor().getPlace())? 0 : 1;
entry.setScore(i==0 ? 0 : scorer.getScore(entry, jumps));
}
}

View File

@@ -63,18 +63,10 @@ public class RouteSearcher {
private Route toRoute(List<Edge<Vendor>> edges){
List<RouteEntry> entries = new ArrayList<>(edges.size()+1);
Vendor buyer = null;
VendorsGraph.VendorsEdge edge = null;
for (int i = 0; i < edges.size(); i++) {
VendorsGraph.VendorsEdge edge = (VendorsGraph.VendorsEdge) edges.get(i);
if (i==0){
RouteEntry entry = new RouteEntry(edge.getSource().getEntry(), false, 0, 0);
List<Order> orders = edge.getOrders();
if (!orders.isEmpty()){
buyer = orders.get(0).getBuyer();
}
entry.addAll(orders);
entries.add(entry);
}
Vendor vendor = edge.getTarget().getEntry();
edge = (VendorsGraph.VendorsEdge) edges.get(i);
Vendor vendor = edge.getSource().getEntry();
RouteEntry entry = new RouteEntry(vendor, edge.isRefill(), edge.getFuel(), edge.getWeight());
if (buyer != null && vendor.equals(buyer)){
entry.setLand(true);
@@ -84,7 +76,7 @@ public class RouteSearcher {
buyer = orders.get(0).getBuyer();
if (vendor instanceof TransitVendor){
Vendor seller = orders.get(0).getSell().getVendor();
for (int j = i-1; j <= 0; j--) {
for (int j = i-1; j >= 0; j--) {
RouteEntry sEntry = entries.get(j);
if (sEntry.is(seller)){
sEntry.addAll(orders);
@@ -97,6 +89,11 @@ public class RouteSearcher {
}
entries.add(entry);
}
if (edge != null) {
RouteEntry entry = new RouteEntry(edge.getTarget().getEntry(), false, 0, 0);
if (buyer != null) entry.setLand(true);
entries.add(entry);
}
return new Route(entries);
}

View File

@@ -18,6 +18,8 @@ public class Scorer {
private final Profile profile;
private final double avgProfit;
private final double minProfit;
private final double maxProfit;
private final double maxScore;
private final double avgDistance;
@@ -28,9 +30,12 @@ public class Scorer {
buyOffers = new HashMap<>(100, 0.9f);
market.getItems().parallelStream().forEach(this::fillOffers);
DoubleSummaryStatistics statProfit = computeProfit();
avgProfit = statProfit.getAverage();
minProfit = statProfit.getMin() / profile.getShip().getCargo();
avgProfit = statProfit.getAverage() / profile.getShip().getCargo();
maxProfit = statProfit.getMax() / profile.getShip().getCargo();
avgDistance = computeAvgDistance();
maxScore = getScore(0, statProfit.getMax()*2, 0,0,0);
maxScore = getScore(1, statProfit.getMax(), 0, 1, 0);
}
public Profile getProfile() {
@@ -60,30 +65,64 @@ public class Scorer {
}
public double getAvgProfit() {
return avgProfit;
return avgProfit * profile.getShip().getCargo();
}
public double getMaxScore() {
return maxScore;
}
public double getAvgDistance() {
return avgDistance;
}
public double getFuel(double distance){
return profile.getShip().getFuelCost(distance);
}
public double getScore(RouteEntry entry, int jumps) {
int lands = entry.isLand() ? 1 : 0;
return getScore(entry.getVendor(), entry.getProfit(), jumps, lands, entry.getFuel());
}
public double getScore(Vendor vendor, double profit, int jumps, int lands, double fuel) {
return getScore(vendor.getDistance(), profit, jumps, lands, fuel);
}
public double getTransitScore(double fuel){
LOG.trace("Compute transit score fuel={}", fuel);
double profit = maxProfit;
profit -= profile.getFuelPrice() * fuel / profile.getShip().getCargo();
double score = 1;
score -= profile.getLandMult();
score -= profile.getJumpMult();
score = score * profit;
if (avgDistance > 0) {
score -= - avgProfit * profile.getDistanceMult();
}
LOG.trace("score={}", score);
return score;
}
public double getScore(double distance, double profit, int jumps, int lands, double fuel){
LOG.trace("Compute score distance={}, profit={}, jumps={}, lands={}, fuel={}", distance, profit, jumps, lands, fuel);
double score = profit;
if (avgDistance > 0 && profit > 0) {
score -= profile.getDistanceMult() * getAvgProfit() * (distance - avgDistance) / avgDistance;
profit -= profile.getFuelPrice() * fuel;
profit = profit / profile.getShip().getCargo();
double score = 1;
if (profit > 0) {
score -= profile.getJumpMult() * (jumps - 1);
score -= profile.getLandMult() * lands;
if (score == 0) {
score = profit;
} else {
score = score * profit;
}
if (avgDistance > 0) {
score -= avgProfit * profile.getDistanceMult() * (distance - avgDistance) / avgDistance;
}
} else {
score = profit;
}
score -= profile.getLandMult() * lands * getAvgProfit();
score -= profile.getFuelPrice() * fuel;
score -= profile.getJumpMult() * jumps * getAvgProfit();
LOG.trace("score={}", score);
return score;
}

View File

@@ -42,9 +42,13 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
}
@Override
protected double onConnect(Vendor entry) {
double nextlimit = super.onConnect(entry);
if (entry instanceof TransitVendor && vertex.getEntry().getPlace().equals(entry.getPlace())) nextlimit = -1;
protected double onConnect(Vendor buyer) {
double nextlimit = super.onConnect(buyer);
Vendor seller = vertex.getEntry();
if (nextlimit > 0){
if (buyer instanceof TransitVendor && seller.getPlace().equals(buyer.getPlace())) nextlimit = -1;
if (seller instanceof TransitVendor && seller.getPlace().equals(buyer.getPlace())) nextlimit = -1;
}
return nextlimit;
}
@@ -83,9 +87,15 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
@Override
protected double computeWeight() {
int jumps = source.getEntry().getPlace().equals(target.getEntry().getPlace())? 0 : 1;
int lands = refill && orders.isEmpty() || isTarget ? 1 : 0;
double score = scorer.getScore(target.getEntry(), getProfit(), jumps, lands, fuel);
return scorer.getMaxScore() - score;
int lands = refill || !orders.isEmpty() || isTarget ? 1 : 0;
boolean transit = lands == 0 && source.getEntry() instanceof TransitVendor || target.getEntry() instanceof TransitVendor;
double profit = getProfit();
double score = transit ? scorer.getTransitScore(fuel) :
scorer.getScore(target.getEntry(), profit, jumps, lands, fuel);
score = scorer.getMaxScore() - score;
if (score < 0)
score = 0;
return score;
}
}
@@ -101,7 +111,7 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
}
@Override
protected CostTraversalEntry travers(CostTraversalEntry entry, List<Edge<Vendor>> head, Edge<Vendor> edge, Vendor target) {
protected CostTraversalEntry travers(final CostTraversalEntry entry, final List<Edge<Vendor>> head, final Edge<Vendor> edge, final Vendor target) {
VendorsTraversalEntry ve = (VendorsTraversalEntry)entry;
double balance = ve.balance;
Vendor buyer = edge.getTarget().getEntry();
@@ -123,7 +133,7 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
ConnectibleEdge<Vendor> cedge = (ConnectibleEdge<Vendor>) ce.getEdge();
VendorsEdge addingEdge = new VendorsEdge(cedge.getSource(), cedge.getTarget(), cedge.isRefill(), cedge.getFuel(), target.equals(buyer));
addingEdge.setOrders(orders);
return new VendorsTraversalEntry(ce, head, addingEdge, balance+addingEdge.getProfit());
return new VendorsTraversalEntry(head, addingEdge, entry.getWeight(), ce.getFuel(), balance+addingEdge.getProfit());
}
protected class VendorsTraversalEntry extends CCostTraversalEntry {
@@ -134,8 +144,8 @@ public class VendorsGraph extends ConnectibleGraph<Vendor> {
this.balance = balance;
}
protected VendorsTraversalEntry(CCostTraversalEntry entry, List<Edge<Vendor>> head, Edge<Vendor> edge, double balance) {
super(head, edge, entry.getWeight(), entry.getFuel());
protected VendorsTraversalEntry(List<Edge<Vendor>> head, Edge<Vendor> edge, double cost, double fuel, double balance) {
super(head, edge, cost, fuel);
this.balance = balance;
}

View File

@@ -82,6 +82,11 @@ public abstract class AbstractGraph<T> implements Graph<T> {
return minJumps;
}
@Override
public int getMinLevel() {
return root.getLevel() - minJumps;
}
protected abstract class GraphBuilder extends RecursiveAction {
protected final Vertex<T> vertex;
protected final Collection<T> set;

View File

@@ -42,7 +42,7 @@ public class Crawler<T> {
if (count > 1) {
Vertex<T> s = graph.getRoot();
s.sortEdges();
found = bfs(start(s), target, 0, count);
found = bfs(start(s), target, graph.getMinLevel(), count);
} else {
found = dfs(start(graph.getRoot()), target, t.getLevel() + 1, count);
}
@@ -58,7 +58,7 @@ public class Crawler<T> {
Vertex<T> t = graph.getVertex(target);
int found = 0;
if (t != null) {
found = ucs(start(graph.getRoot()), target, 0, count);
found = ucs(start(graph.getRoot()), target, graph.getMinLevel(), count);
}
LOG.debug("Found {} paths", found);
}
@@ -153,7 +153,7 @@ public class Crawler<T> {
found++;
if (found >= count) break;
}
if (edge.getTarget().isSingle() || deep >= source.getLevel()){
if (edge.getTarget().isSingle()){
continue;
}
head = getCopyList(entry.head, edge);
@@ -166,7 +166,7 @@ public class Crawler<T> {
//put only 2 entry for iterate
while (iterator.hasNext()){
edge = iterator.next();
if (deep < source.getLevel() && !edge.getTarget().isSingle() || edge.isConnect(target)) {
if (deep <= source.getLevel() && !edge.getTarget().isSingle() || edge.isConnect(target)) {
LOG.trace("Add edge {} to queue", edge);
queue.add(travers(entry, head, edge, target));
}

View File

@@ -8,4 +8,6 @@ public interface Graph<T> {
Vertex<T> getRoot();
int getMinJumps();
int getMinLevel();
}

View File

@@ -18,10 +18,10 @@ public class Profile {
this.ship = ship;
refill = true;
scoreOrdersCount = 5;
distanceMult = 1;
landMult = 1;
fuelPrice = 1;
jumpMult = 0.01;
distanceMult = 0.08;
landMult = 0.95;
fuelPrice = 100;
jumpMult = 0.008;
}
public double getBalance() {

View File

@@ -93,6 +93,11 @@ public class TransitVendor implements Vendor {
return d == 0 ? 0 : d > 0 ? 1 : -1;
}
@Override
public boolean canRefill() {
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -108,6 +113,6 @@ public class TransitVendor implements Vendor {
@Override
public String toString() {
return "Transit - "+place;
return "Transit "+place;
}
}

View File

@@ -20,6 +20,8 @@ public class RouteSearcherTest extends Assert{
private Place ithaca;
private Place lhs3262;
private Place morgor;
private Place lhs3006;
@Before
public void setUp() throws Exception {
@@ -27,6 +29,8 @@ public class RouteSearcherTest extends Assert{
world = Store.loadFromFile(is);
ithaca = world.get("Ithaca");
lhs3262 = world.get("LHS 3262");
morgor = world.get("Morgor");
lhs3006 = world.get("LHS 3006");
MarketFilter filter = new MarketFilter();
fWorld = new FilteredMarket(world, filter);
@@ -38,17 +42,30 @@ public class RouteSearcherTest extends Assert{
// Ithaca (Palladium to LHS 3262) -> Morgor -> LHS 3006 -> LHS 3262 (Consumer Technology to Ithaca) -> LHS 3006 -> Morgor -> Ithaca
// Profit: 981200, avg: 490600, distance: 67.5, lands: 2
Vendor ithaca_st = ithaca.get().iterator().next();
Vendor lhs3262_st = lhs3262.get().iterator().next();
Vendor morgor_st = morgor.get().iterator().next();
Vendor lhs3006_st = lhs3006.get().iterator().next();
Ship ship = new Ship();
ship.setCargo(440); ship.setTank(16);
ship.setCargo(440); ship.setTank(15);
ship.setEngine(5, 'A'); ship.setMass(466);
Profile profile = new Profile(ship);
profile.setBalance(6000000); profile.setJumps(6);
profile.setRoutesCount(10);
profile.setRoutesCount(100);
Scorer scorer = new Scorer(fWorld, profile);
LOG.info("Start test routes");
RouteSearcher searcher = new RouteSearcher(scorer);
Route route = new Route(new RouteEntry(ithaca_st, false, 3.3789702637348586d, 0));
route.add(new RouteEntry(morgor_st, false, 4.137765020523591d, 0));
route.add(new RouteEntry(lhs3006_st, false, 4.0674474942172765d, 0));
route.add(new RouteEntry(lhs3262_st, true, 4.149937831634785d, 0));
route.add(new RouteEntry(lhs3006_st, false, 4.1292528548103d, 0));
route.add(new RouteEntry(morgor_st, false, 3.3050364899848566, 0));
route.add(new RouteEntry(ithaca_st, false, 3.3483447506734136, 0));
RouteFiller filler = new RouteFiller(scorer);
filler.fill(route);
List<Route> apaths = searcher.getRoutes(ithaca_st, ithaca_st, fWorld.getMarkets(true).collect(Collectors.toList()));
Route actual = apaths.stream().findFirst().get();
//assertTrue("Routes is different",expect.isRoute(actual));

View File

@@ -108,6 +108,87 @@ public class ScorerTest extends Assert {
}
@Test
public void testScore2() throws Exception {
Ship ship = new Ship();
ship.setCargo(100);
Profile profile = new Profile(ship);
LOG.info("Start score test, balance 10000000");
profile.setBalance(1000000);
Scorer scorer = new Scorer(fWorld, profile);
double transitScore = scorer.getTransitScore(4);
double transitScore2 = scorer.getTransitScore(6);
double transitScore3 = scorer.getTransitScore(2);
assertTrue(transitScore > transitScore2);
assertTrue(transitScore3 > transitScore);
double score = scorer.getScore(scorer.getAvgDistance(), 0, 1, 1, 4);
double score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()/2, 1, 1, 4);
double score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()*10, 1, 1, 4);
double score3 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
assertTrue(score < score1);
assertTrue(score1 < score3);
assertTrue(score3 < score2);
assertTrue(score3 < score2);
assertTrue(Math.abs(score2/score1) >= 20);
assertTrue(Math.abs(score3/score1) >= 2);
assertTrue(Math.abs(score2/score3) >= 10);
score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 0, 1, 4);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 2, 1, 4);
assertTrue(score1 > score2);
assertTrue(score2 > score3);
score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 0, 4);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 2, 4);
assertTrue(score1 > score2);
assertTrue(score2 > score3);
score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 3);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 5);
assertTrue(score1 > score2);
assertTrue(score2 > score3);
score = scorer.getScore(0, scorer.getAvgProfit(), 1, 1, 4);
score1 = scorer.getScore(scorer.getAvgDistance()/2, scorer.getAvgProfit(), 1, 1, 4);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance()*2, scorer.getAvgProfit(), 1, 1, 4);
assertTrue(score > score1);
assertTrue(score1 > score2);
assertTrue(score2 > score3);
score1 = scorer.getScore(scorer.getAvgDistance()/2, scorer.getAvgProfit(), 1, 1, 4);
score2 = scorer.getScore(scorer.getAvgDistance()*2, scorer.getAvgProfit()*2, 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance()*2, scorer.getAvgProfit()*4, 1, 1, 4);
assertTrue(score1 > score2);
assertTrue(score3 > score1);
score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()/2, 0, 1, 4);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()*2, 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()*4, 0, 1, 4);
assertTrue(score2 > score1);
assertTrue(score3 > score2);
transitScore = scorer.getTransitScore(4);
score = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit(), 1, 1, 4);
score1 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()/2, 1, 1, 4);
score2 = scorer.getScore(scorer.getAvgDistance(), scorer.getAvgProfit()*10, 1, 1, 4);
score3 = scorer.getScore(scorer.getAvgDistance(), 0, 1, 1, 4);
assertTrue(transitScore > score);
assertTrue(transitScore > score1);
assertTrue(transitScore < score2);
assertTrue(transitScore > score3);
}
@After
public void tearDown() throws Exception {
world = null;

View File

@@ -4,4 +4,4 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p: %d{dd.MM.yyyy HH:mm:ss} (%F:%L) - %m%n
log4j.logger.ru.trader.analysis.graph = TRACE
#log4j.logger.ru.trader.analysis.graph = TRACE