profile syntax: syntactic sugar

This commit is contained in:
Arndt 2015-03-01 13:04:11 +01:00
parent 8676f5e081
commit 6811ea524e
5 changed files with 245 additions and 122 deletions

View file

@ -292,7 +292,7 @@ final class OsmPath implements OsmLinkHolder
+ "\t" + linkturncost + "\t" + linkturncost
+ "\t" + linknodecost + "\t" + linknodecost
+ "\t" + linkinitcost + "\t" + linkinitcost
+ rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description ); + "\t" + rc.expctxWay.getKeyValueDescription( link.counterLinkWritten, description );
} }
if ( stopAtEndpoint ) if ( stopAtEndpoint )

View file

@ -31,9 +31,18 @@ final class BExpression
// Parse the expression and all subexpression // Parse the expression and all subexpression
public static BExpression parse( BExpressionContext ctx, int level ) throws Exception public static BExpression parse( BExpressionContext ctx, int level ) throws Exception
{
return parse( ctx, level, null );
}
private static BExpression parse( BExpressionContext ctx, int level, String optionalToken ) throws Exception
{ {
boolean brackets = false; boolean brackets = false;
String operator = ctx.parseToken(); String operator = ctx.parseToken();
if ( optionalToken != null && optionalToken.equals( operator ) )
{
operator = ctx.parseToken();
}
if ( "(".equals( operator ) ) if ( "(".equals( operator ) )
{ {
brackets = true; brackets = true;
@ -145,6 +154,16 @@ final class BExpression
exp.typ = VARIABLE_EXP; exp.typ = VARIABLE_EXP;
exp.variableIdx = idx; exp.variableIdx = idx;
} }
else if ( "true".equals( operator ) )
{
exp.numberValue = 1.f;
exp.typ = NUMBER_EXP;
}
else if ( "false".equals( operator ) )
{
exp.numberValue = 0.f;
exp.typ = NUMBER_EXP;
}
else else
{ {
try try
@ -163,17 +182,17 @@ final class BExpression
// parse operands // parse operands
if ( nops > 0 ) if ( nops > 0 )
{ {
exp.op1 = BExpression.parse( ctx, level+1 ); exp.op1 = BExpression.parse( ctx, level+1, exp.typ == ASSIGN_EXP ? "=" : null );
} }
if ( nops > 1 ) if ( nops > 1 )
{ {
if ( ifThenElse ) checkExpectedToken( ctx, "then" ); if ( ifThenElse ) checkExpectedToken( ctx, "then" );
exp.op2 = BExpression.parse( ctx, level+1 ); exp.op2 = BExpression.parse( ctx, level+1, null );
} }
if ( nops > 2 ) if ( nops > 2 )
{ {
if ( ifThenElse ) checkExpectedToken( ctx, "else" ); if ( ifThenElse ) checkExpectedToken( ctx, "else" );
exp.op3 = BExpression.parse( ctx, level+1 ); exp.op3 = BExpression.parse( ctx, level+1, null );
} }
if ( brackets ) if ( brackets )
{ {

View file

@ -19,6 +19,7 @@ import java.util.TreeMap;
import btools.util.BitCoderContext; import btools.util.BitCoderContext;
import btools.util.Crc32; import btools.util.Crc32;
import java.util.Random;
public final class BExpressionContext public final class BExpressionContext
@ -172,7 +173,7 @@ public final class BExpressionContext
decode( ld2, false, ab ); decode( ld2, false, ab );
for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names for( int inum = 0; inum < lookupValues.size(); inum++ ) // loop over lookup names
{ {
if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding " + getKeyValueDescription(false, ab) ); if ( ld2[inum] != ld[inum] ) throw new RuntimeException( "assertion failed encoding inum=" + inum + " val=" + ld[inum] + " " + getKeyValueDescription(false, ab) );
} }
return ab; return ab;
@ -471,6 +472,51 @@ public final class BExpressionContext
return null; return null;
} }
/**
* generate random values for regression testing
*/
public int[] generateRandomValues( Random rnd )
{
int[] data = createNewLookupData();
data[0] = 2*rnd.nextInt( 2 ); // reverse-direction = 0 or 2
for( int inum = 1; inum < data.length; inum++ )
{
int nvalues = lookupValues.get( inum ).length;
data[inum] = 0;
if ( inum > 1 && rnd.nextInt( 10 ) > 0 ) continue; // tags other than highway only 10%
data[inum] = rnd.nextInt( nvalues );
}
lookupDataValid = true;
return data;
}
public void assertAllVariablesEqual( BExpressionContext other )
{
int nv = variableData.length;
int nv2 = other.variableData.length;
if ( nv != nv2 ) throw new RuntimeException( "mismatch in variable-count: " + nv + "<->" + nv2 );
for( int i=0; i<nv; i++ )
{
if ( variableData[i] != other.variableData[i] )
{
throw new RuntimeException( "mismatch in variable " + variableName(i) + " " + variableData[i] + "<->" + other.variableData[i]
+ "\ntags = " + getKeyValueDescription( false, encode() ) );
}
}
}
private String variableName( int idx )
{
for( Map.Entry<String,Integer> e : variableNumbers.entrySet() )
{
if ( e.getValue().intValue() == idx )
{
return e.getKey();
}
}
throw new RuntimeException( "no variable for index" + idx );
}
/** /**
* add a new lookup-value for the given name to the given lookupData array. * add a new lookup-value for the given name to the given lookupData array.
* If no array is given (null value passed), the value is added to * If no array is given (null value passed), the value is added to

View file

@ -0,0 +1,59 @@
package btools.expressions;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;
import btools.util.BitCoderContext;
import btools.util.Crc32;
import java.util.Random;
public final class ProfileComparator
{
public static void main( String[] args )
{
if ( args.length != 4 )
{
System.out.println( "usage: java ProfileComparator <lookup-file> <profile1> <profile2> <nsamples>" );
return;
}
File lookupFile = new File( args[0] );
File profile1File = new File( args[1] );
File profile2File = new File( args[2] );
int nsamples = Integer.parseInt( args[3] );
testContext( lookupFile, profile1File, profile2File, nsamples, "way" );
testContext( lookupFile, profile1File, profile2File, nsamples, "node" );
}
private static void testContext( File lookupFile, File profile1File, File profile2File, int nsamples, String contextName )
{
// read lookup.dat + profiles
BExpressionMetaData meta1 = new BExpressionMetaData();
BExpressionMetaData meta2 = new BExpressionMetaData();
BExpressionContext expctx1 = new BExpressionContext(contextName, 4096, meta1 );
BExpressionContext expctx2 = new BExpressionContext(contextName, 4096, meta2 );
meta1.readMetaData( lookupFile );
meta2.readMetaData( lookupFile );
expctx1.parseFile( profile1File, "global" );
expctx2.parseFile( profile2File, "global" );
Random rnd = new Random();
for( int i=0; i<nsamples; i++ )
{
int[] data = expctx1.generateRandomValues( rnd );
expctx1.evaluate( data );
expctx2.evaluate( data );
expctx1.assertAllVariablesEqual( expctx2 );
}
}
}

View file

@ -8,21 +8,21 @@
# Use the following switches to change behaviour # Use the following switches to change behaviour
# (1=yes, 0=no): # (1=yes, 0=no):
assign consider_elevation 1 # set to 0 to ignore elevation in routing assign consider_elevation = true # set to false to ignore elevation in routing
assign allow_steps 1 # set to 0 to disallow steps assign allow_steps = true # set to false to disallow steps
assign allow_ferries 1 # set to 0 to disallow ferries assign allow_ferries = true # set to false to disallow ferries
assign ignore_cycleroutes 0 # set to 1 for better elevation results assign ignore_cycleroutes = false # set to true for better elevation results
assign stick_to_cycleroutes 0 # set to 1 to just follow cycleroutes assign stick_to_cycleroutes = false # set to true to just follow cycleroutes
assign avoid_unsafe 0 # set to 1 to avoid standard highways assign avoid_unsafe = false # set to true to avoid standard highways
assign validForBikes 1 assign validForBikes = true
# the elevation parameters # the elevation parameters
assign downhillcost switch consider_elevation 60 0 assign downhillcost = if consider_elevation then 60 else 0
assign downhillcutoff 1.5 assign downhillcutoff = 1.5
assign uphillcost 0 assign uphillcost = 0
assign uphillcutoff 1.5 assign uphillcutoff = 1.5
---context:way # following code refers to way-tags ---context:way # following code refers to way-tags
@ -30,14 +30,25 @@ assign uphillcutoff 1.5
# pre-calculate some logical expressions # pre-calculate some logical expressions
# #
assign any_cycleroute or route_bicycle_icn=yes or route_bicycle_ncn=yes or route_bicycle_rcn=yes route_bicycle_lcn=yes assign any_cycleroute =
assign nodeaccessgranted or any_cycleroute lcn=yes if route_bicycle_icn=yes then true
else if route_bicycle_ncn=yes then true
else if route_bicycle_rcn=yes then true
else if route_bicycle_lcn=yes then true
else false
assign is_ldcr and any_cycleroute not ignore_cycleroutes assign nodeaccessgranted =
assign isbike or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes if any_cycleroute then true
assign ispaved or surface=paved or surface=asphalt or surface=concrete surface=paving_stones else lcn=yes
assign isunpaved not or surface= or ispaved or surface=fine_gravel surface=cobblestone
assign probablyGood or ispaved and isbike not isunpaved assign is_ldcr =
if ignore_cycleroutes then false
else any_cycleroute
assign isbike = or bicycle=yes or or bicycle=permissive bicycle=designated lcn=yes
assign ispaved = surface=paved|asphalt|concrete|paving_stones
assign isunpaved = not or surface= or ispaved surface=fine_gravel|cobblestone
assign probablyGood = or ispaved and isbike not isunpaved
# #
@ -46,59 +57,53 @@ assign probablyGood or ispaved and isbike not isunpaved
# (Suppressing turncost while following longdistance-cycleways # (Suppressing turncost while following longdistance-cycleways
# makes them a little bit more magnetic) # makes them a little bit more magnetic)
# #
assign turncost switch is_ldcr 0 90 assign turncost = if is_ldcr then 0 else 90
# #
# calculate the initial cost # calculate the initial cost
# this is added to the total cost each time the costfactor # this is added to the total cost each time the costfactor
# changed # changed
# #
assign initialcost switch route=ferry 10000 0 assign initialcost = if route=ferry then 10000 else 0
# #
# implicit access here just from the motorroad tag # implicit access here just from the motorroad tag
# (implicit access rules from highway tag handled elsewhere) # (implicit access rules from highway tag handled elsewhere)
# #
assign defaultaccess assign defaultaccess =
switch access= if access= then not motorroad=yes
not motorroad=yes else if access=private|no then false
switch or access=private access=no else true
0
1
# #
# calculate logical bike access # calculate logical bike access
# #
assign bikeaccess assign bikeaccess =
or any_cycleroute if any_cycleroute then true
switch bicycle= else if bicycle= then
switch vehicle= (
defaultaccess if vehicle= then defaultaccess
switch or vehicle=private vehicle=no else not vehicle=private|no
0 )
1 else not bicycle=private|no|dismount
not or bicycle=private or bicycle=no bicycle=dismount
# #
# calculate logical foot access # calculate logical foot access
# #
assign footaccess assign footaccess =
or bikeaccess if bikeaccess then true
or bicycle=dismount else if bicycle=dismount then true
switch foot= else if foot= then defaultaccess
defaultaccess else not foot=private|no
not or foot=private foot=no
# #
# if not bike-, but foot-acess, just a moderate penalty, # if not bike-, but foot-acess, just a moderate penalty,
# otherwise access is forbidden # otherwise access is forbidden
# #
assign accesspenalty assign accesspenalty =
switch bikeaccess if bikeaccess then 0
0 else if footaccess then 4
switch footaccess else 100000
4
100000
# #
# handle one-ways. On primary roads, wrong-oneways should # handle one-ways. On primary roads, wrong-oneways should
@ -106,19 +111,21 @@ assign accesspenalty
# 4 to the costfactor (making it at least 5 - you are allowed # 4 to the costfactor (making it at least 5 - you are allowed
# to push your bike) # to push your bike)
# #
assign oneway assign oneway =
switch oneway= if oneway= then junction=roundabout else oneway=yes|true|1
junction=roundabout
or oneway=yes or oneway=true oneway=1 assign onewaypenalty =
if ( if reversedirection=yes then oneway else oneway=-1 ) then
(
if ( cycleway=opposite|opposite_lane|opposite_track ) then 0
else if ( oneway:bicycle=no ) then 0
else if ( highway=primary|primary_link ) then 50
else if ( highway=secondary|secondary_link ) then 30
else if ( highway=tertiary|tertiary_link ) then 20
else 4.0
)
else 0.0
assign onewaypenalty
switch switch reversedirection=yes oneway oneway=-1
switch or cycleway=opposite or cycleway=opposite_lane or cycleway=opposite_track oneway:bicycle=no 0
switch or highway=primary highway=primary_link 50
switch or highway=secondary highway=secondary_link 30
switch or highway=tertiary highway=tertiary_link 20
4.0
0.0
# #
# calculate the cost-factor, which is the factor # calculate the cost-factor, which is the factor
@ -127,106 +134,98 @@ assign onewaypenalty
# must be >=1 and it's supposed to be close to 1 for # must be >=1 and it's supposed to be close to 1 for
# the type of way the routing profile is searching for # the type of way the routing profile is searching for
# #
assign costfactor assign costfactor =
add max onewaypenalty accesspenalty add ( max onewaypenalty accesspenalty )
switch and highway= not route=ferry 100000 if ( and highway= not route=ferry ) then 100000
# #
# steps and ferries are special. Note this is handled # steps and ferries are special. Note this is handled
# before the cycleroute-switch, to be able # before the cycleroute-switch, to be able
# to really exlude them be setting cost to infinity # to really exlude them be setting cost to infinity
# #
switch highway=steps switch allow_steps 40 100000 else if ( highway=steps ) then ( if allow_steps then 40 else 100000 )
switch route=ferry switch allow_ferries 5.67 100000 else if ( route=ferry ) then ( if allow_ferries then 5.67 else 100000 )
# #
# handle long-distance cycle-routes. # handle long-distance cycle-routes.
# #
switch is_ldcr 1 # always treated as perfect (=1) else if ( is_ldcr ) then 1 # always treated as perfect (=1)
add switch stick_to_cycleroutes 0.5 0.05 # everything else somewhat up else
add ( if stick_to_cycleroutes then 0.5 else 0.05 ) # everything else somewhat up
# #
# some other highway types # some other highway types
# #
switch highway=pedestrian 3 if ( highway=pedestrian ) then 3
switch highway=bridleway 5 else if ( highway=bridleway ) then 5
switch highway=cycleway 1 else if ( highway=cycleway ) then 1
switch or highway=residential highway=living_street switch isunpaved 1.5 1.1 else if ( highway=residential|living_street ) then ( if isunpaved then 1.5 else 1.1 )
switch highway=service switch isunpaved 1.6 1.3 else if ( highway=service ) then ( if isunpaved then 1.6 else 1.3 )
# #
# tracks and track-like ways are rated mainly be tracktype/grade # tracks and track-like ways are rated mainly be tracktype/grade
# But note that if no tracktype is given (mainly for road/path/footway) # But note that if no tracktype is given (mainly for road/path/footway)
# it can be o.k. if there's any other hint for quality # it can be o.k. if there's any other hint for quality
# #
switch or highway=track or highway=road or highway=path highway=footway else if ( highway=track|road|path|footway ) then
switch tracktype=grade1 switch probablyGood 1.0 1.3 (
switch tracktype=grade2 switch probablyGood 1.1 2.0 if ( tracktype=grade1 ) then ( if probablyGood then 1.0 else 1.3 )
switch tracktype=grade3 switch probablyGood 1.5 3.0 else if ( tracktype=grade2 ) then ( if probablyGood then 1.1 else 2.0 )
switch tracktype=grade4 switch probablyGood 2.0 5.0 else if ( tracktype=grade3 ) then ( if probablyGood then 1.5 else 3.0 )
switch tracktype=grade5 switch probablyGood 3.0 5.0 else if ( tracktype=grade4 ) then ( if probablyGood then 2.0 else 5.0 )
switch probablyGood 1.0 5.0 else if ( tracktype=grade5 ) then ( if probablyGood then 3.0 else 5.0 )
else ( if probablyGood then 1.0 else 5.0 )
)
# #
# When avoiding unsafe ways, avoid highways without a bike hint # When avoiding unsafe ways, avoid highways without a bike hint
# #
add switch and avoid_unsafe not isbike 2 0 else add ( if ( and avoid_unsafe not isbike ) then 2 else 0 )
# #
# exclude motorways and proposed roads # exclude motorways and proposed roads
# #
switch or highway=motorway highway=motorway_link 100000 if ( highway=motorway|motorway_link ) then 100000
switch or highway=proposed highway=abandoned 100000 else if ( highway=proposed|abandoned ) then 100000
# #
# actuals roads are o.k. if we have a bike hint # actuals roads are o.k. if we have a bike hint
# #
switch or highway=trunk highway=trunk_link switch isbike 1.5 10 else if ( highway=trunk|trunk_link ) then ( if isbike then 1.5 else 10 )
switch or highway=primary highway=primary_link switch isbike 1.2 3 else if ( highway=primary|primary_link ) then ( if isbike then 1.2 else 3 )
switch or highway=secondary highway=secondary_link switch isbike 1.1 1.6 else if ( highway=secondary|secondary_link ) then ( if isbike then 1.1 else 1.6 )
switch or highway=tertiary highway=tertiary_link switch isbike 1.0 1.4 else if ( highway=tertiary|tertiary_link ) then ( if isbike then 1.0 else 1.4 )
switch highway=unclassified switch isbike 1.0 1.3 else if ( highway=unclassified ) then ( if isbike then 1.0 else 1.3 )
# #
# default for any other highway type not handled above # default for any other highway type not handled above
# #
2.0 else 2.0
---context:node # following code refers to node tags ---context:node # following code refers to node tags
assign defaultaccess assign defaultaccess =
switch access= if ( access= ) then true # add default barrier restrictions here!
1 # add default barrier restrictions here! else if ( access=private|no ) then false
switch or access=private access=no else true
0
1
assign bikeaccess assign bikeaccess =
or nodeaccessgranted=yes if nodeaccessgranted=yes then true
switch bicycle= else if bicycle= then
switch vehicle= (
defaultaccess if vehicle= then defaultaccess
switch or vehicle=private vehicle=no else not vehicle=private|no
0 )
1 else not bicycle=private|no|dismount
switch or bicycle=private or bicycle=no bicycle=dismount
0
1
assign footaccess assign footaccess =
or bicycle=dismount if bicycle=dismount then true
switch foot= else if foot= then defaultaccess
defaultaccess else not foot=private|no
switch or foot=private foot=no
0
1
assign initialcost assign initialcost =
switch bikeaccess if bikeaccess then 0
0 else ( if footaccess then 100 else 1000000 )
switch footaccess
100
1000000