Add scaling factor to profiles

This commit is contained in:
Pieter Vander Vennet 2022-10-17 16:15:24 +02:00
parent 43590ad69f
commit d80bff69d7
4 changed files with 52 additions and 61 deletions

View file

@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AspectedRouting.IO.LuaSkeleton;
using AspectedRouting.IO.LuaSnippets;
using AspectedRouting.Language;
using AspectedRouting.Language.Functions;
using AspectedRouting.Language.Typ;
@ -18,7 +18,7 @@ namespace AspectedRouting.IO.itinero1
var access = _skeleton.ToLuaWithTags(_profile.Access);
var oneway = _skeleton.ToLuaWithTags(_profile.Oneway);
var speed = _skeleton.ToLuaWithTags(_profile.Speed);
var impl = string.Join("\n",
"",
"",
@ -54,16 +54,17 @@ namespace AspectedRouting.IO.itinero1
impl +=
"\n local priority = 0\n ";
var tags = new LuaLiteral(Typs.Tags, "tags");
foreach (var (parameterName, expression) in _profile.Priority)
{
var paramInLua = _skeleton.ToLua(new Parameter(parameterName));
var expr = Funcs.Either(Funcs.Id, Funcs.Const, expression).Apply(new LuaLiteral(Typs.Tags, "tags"))
var expr = Funcs.Either(Funcs.Id, Funcs.Const, expression).Apply(tags)
.SpecializeToSmallestType()
.PruneTypes(t => !(t is Curry))
.Optimize(out _);
if (expr.Types.Any(t => t.Name.Equals(Typs.Bool.Name)))
{
expr = Funcs.Parse.Apply(expr).SpecializeToSmallestType();
@ -77,8 +78,14 @@ namespace AspectedRouting.IO.itinero1
);
}
var scalingFactor = Funcs.Default.Apply(new Constant(Typs.Double, 1.0), _profile.ScalingFactor, tags);
impl += string.Join("\n",
" -- Calculate the scaling factor",
" local scalingfactor",
Snippets.Convert(_skeleton, "scalingfactor", scalingFactor.SpecializeToSmallestType()),
"",
"priority = priority * scalingfactor",
"",
"",
" if (priority <= 0) then",
@ -100,10 +107,10 @@ namespace AspectedRouting.IO.itinero1
"end"
);
return impl;
return impl;
}
private (string functionName, string implementation) GenerateBehaviourFunction(
string behaviourName,
Dictionary<string, IExpression> behaviourParameters)
@ -115,12 +122,12 @@ namespace AspectedRouting.IO.itinero1
_skeleton.AddDep("copy_tags");
var usedkeys = _profile.AllExpressionsFor(behaviourName, _context)
.PossibleTagsRecursive(_context)
.Select(t => "\""+ t.Key+"\"")
.Select(t => "\"" + t.Key + "\"")
.ToHashSet();
_skeleton.AddDep("remove_relation_prefix");
var impl = string.Join("\n",
"behaviour_"+functionName+"_used_keys = create_set({"+ string.Join(", " , usedkeys) + "})",
"behaviour_" + functionName + "_used_keys = create_set({" + string.Join(", ", usedkeys) + "})",
"--[[",
description,
"]]",

View file

@ -20,7 +20,7 @@ namespace AspectedRouting.IO.itinero2
var aspects = new List<string>();
var tags = new LuaLiteral(Typs.Tags, "tags");
foreach (var (paramName, expr) in _profile.Priority)
{
var weightExpr = parameters[paramName].Evaluate(_context);
@ -31,7 +31,7 @@ namespace AspectedRouting.IO.itinero2
// The expression might still have multiple typings,
// which take inputs different from 'Tags', so we specialize the expr first
var appliedExpr = Funcs.Either(Funcs.Id, Funcs.Const, expr)
.Apply(new LuaLiteral(Typs.Tags, "tags").SpecializeToSmallestType())
.Apply(tags)
.PruneTypes(tp => !(tp is Curry));
var exprSpecialized = appliedExpr.Optimize(out _);
@ -48,7 +48,8 @@ namespace AspectedRouting.IO.itinero2
aspects.Add(weight + " * " + exprInLua);
}
Console.WriteLine(aspects.Lined());
var scalingFactor = Funcs.Default.Apply(new Constant(Typs.Double, 1.0), _profile.ScalingFactor, tags)
.SpecializeToSmallestType();
var code = new List<string>
{
"--[[",
@ -58,7 +59,10 @@ namespace AspectedRouting.IO.itinero2
"function calculate_priority(parameters, tags, result, access, oneway, speed)",
" local distance = 1",
" local priority = \n " + string.Join(" +\n ", aspects),
" return priority",
"",
"local scalingfactor",
Snippets.Convert(_skeleton, "scalingfactor", scalingFactor),
" return priority * scalingfactor",
"end"
};
return code.Lined();

View file

@ -24,10 +24,10 @@ namespace AspectedRouting.IO.jsonParser
return null;
}
Console.Write("Parsing " + fileName+"... ");
Console.Write("Parsing " + fileName + "... ");
var aspect = doc.RootElement.ParseAspect(fileName, c);
var aspect= doc.RootElement.ParseAspect(fileName, c);
Console.WriteLine($"\rAspect {aspect.Name} has type {string.Join(",", aspect.ExpressionImplementation.Types)}");
return aspect;
}
@ -113,6 +113,7 @@ namespace AspectedRouting.IO.jsonParser
var access = ParseProfileProperty(e, contextWithParameters, "access").Finalize();
var oneway = ParseProfileProperty(e, contextWithParameters, "oneway").Finalize();
var speed = ParseProfileProperty(e, contextWithParameters, "speed").Finalize();
var scalingFactor = ParseProfileProperty(e, contextWithParameters, "scalingfactor", Funcs.Const.Apply(new Constant(1))).Finalize();
var obstacle_access = ParseProfileProperty(e, contextWithParameters, "obstacleaccess", Funcs.Const.Apply(new Constant(new Var("any"), null))).Finalize();
var obstacle_cost = ParseProfileProperty(e, contextWithParameters, "obstaclecost", Funcs.Const.Apply(new Constant(new Var("any0"), null))).Finalize();
@ -174,14 +175,15 @@ namespace AspectedRouting.IO.jsonParser
speed,
obstacle_access, obstacle_cost,
weights,
scalingFactor,
metadata,
lastChange
);
}
private static readonly IExpression _mconst = Funcs.EitherFunc.Apply( Funcs.Id, Funcs.Const);
private static readonly IExpression _mconst = Funcs.EitherFunc.Apply(Funcs.Id, Funcs.Const);
private static readonly IExpression _mappingWrapper = Funcs.EitherFunc.Apply( Funcs.Id, Funcs.StringStringToTags);
private static readonly IExpression _mappingWrapper = Funcs.EitherFunc.Apply(Funcs.Id, Funcs.StringStringToTags);
private static IExpression ParseMapping(IEnumerable<JsonProperty> allArgs, Context context)
{
@ -262,7 +264,7 @@ namespace AspectedRouting.IO.jsonParser
var exprs = e.EnumerateArray().Select(json =>
Funcs.Either(Funcs.Id, Funcs.Const, json.ParseExpression(context)))
.ToList();
var list = new Constant(exprs);
return Funcs.Either(Funcs.Id, Funcs.ListDot, list);
}
@ -310,18 +312,19 @@ namespace AspectedRouting.IO.jsonParser
{
// This is a parameter, the type of it is free
if (context.Parameters.TryGetValue(s.Substring(1), out var param))
{
{
return new Parameter(s).Specialize(param.Types);
}
return new Parameter(s);
}
return new Constant(s);
}
if (e.ValueKind == JsonValueKind.Null) {
if (e.ValueKind == JsonValueKind.Null)
{
return new Constant(new Var("a"), null);
}
@ -375,7 +378,7 @@ namespace AspectedRouting.IO.jsonParser
foreach (var argName in func.ArgNames.GetRange(1, func.ArgNames.Count - 1))
// We skip the first argument, that one is already added
// We skip the first argument, that one is already added
{
args.Add(allExprs[argName]);
}
@ -405,7 +408,7 @@ namespace AspectedRouting.IO.jsonParser
if (!prop.Name.StartsWith("$")) continue;
var f = (IExpression) Funcs.BuiltinByName(prop.Name);
var f = (IExpression)Funcs.BuiltinByName(prop.Name);
if (f == null || f.Types.Count() == 0)
{
throw new KeyNotFoundException($"The builtin function {prop.Name} was not found");
@ -434,7 +437,7 @@ namespace AspectedRouting.IO.jsonParser
// It gets an extra argument injected
var neededKeys = fArg.PossibleTags().Keys.ToList();
var neededKeysArg = new Constant(new ListType(Typs.String), neededKeys);
f = f.Apply(new[] {neededKeysArg});
f = f.Apply(new[] { neededKeysArg });
}
var appliedDot = new Apply(new Apply(Funcs.Dot, f), fArg);
@ -524,7 +527,7 @@ namespace AspectedRouting.IO.jsonParser
$"filename is {filepath}, declared name is {name}");
}
var keys = (IEnumerable<string>) expr.PossibleTags()?.Keys ?? new List<string>();
var keys = (IEnumerable<string>)expr.PossibleTags()?.Keys ?? new List<string>();
foreach (var key in keys)
{
if (!key.Trim().Equals(key))

View file

@ -34,6 +34,7 @@ namespace AspectedRouting.Language.Expression
public Dictionary<string, IExpression> Priority { get; }
public IExpression ScalingFactor { get; }
/**
* Moment of last change of any upstream file
@ -45,7 +46,7 @@ namespace AspectedRouting.Language.Expression
Dictionary<string, Dictionary<string, IExpression>> behaviours,
IExpression access, IExpression oneway, IExpression speed,
IExpression obstacleAccess, IExpression obstacleCost,
Dictionary<string, IExpression> priority, List<string> metadata, DateTime lastChange)
Dictionary<string, IExpression> priority, IExpression scalingFactor, List<string> metadata, DateTime lastChange)
{
Name = name;
Description = description;
@ -58,6 +59,7 @@ namespace AspectedRouting.Language.Expression
ObstacleAccess = obstacleAccess.Optimize(out _);
ObstacleCost = obstacleCost.Optimize(out _);
Priority = priority;
ScalingFactor = scalingFactor;
Metadata = metadata;
LastChange = lastChange;
DefaultParameters = defaultParameters;
@ -74,7 +76,7 @@ namespace AspectedRouting.Language.Expression
{
if (e == null)
{
throw new Exception("No expression given for " +name);
throw new Exception("No expression given for " + name);
}
if (e.Types.Count() == 1)
{
@ -91,7 +93,7 @@ namespace AspectedRouting.Language.Expression
l.AddRange(DefaultParameters.Values);
l.AddRange(Behaviours.Values.SelectMany(b => b.Values));
l.AddRange(Priority.Values);
var allExpr = new List<IExpression>();
allExpr.AddRange(l);
@ -207,43 +209,18 @@ namespace AspectedRouting.Language.Expression
}
var aspectWeightObj = new Apply(
var aspectWeight = new Apply(
Funcs.EitherFunc.Apply(Funcs.Id, Funcs.Const, expression)
, new Constant(tags)).Evaluate(c);
, new Constant(tags)).EvaluateDouble(paramName, c);
double aspectWeight;
switch (aspectWeightObj)
{
case bool b:
aspectWeight = b ? 1.0 : 0.0;
break;
case double d:
aspectWeight = d;
break;
case int j:
aspectWeight = j;
break;
case string s:
if (s.Equals("yes"))
{
aspectWeight = 1.0;
break;
}
else if (s.Equals("no"))
{
aspectWeight = 0.0;
break;
}
throw new Exception($"Invalid value as result for {paramName}: got string {s}");
default:
throw new Exception($"Invalid value as result for {paramName}: got object {aspectWeightObj}");
}
weightExplanation.Add($"({paramName} = {aspectInfluence}) * {aspectWeight}");
priority += aspectInfluence * aspectWeight;
}
var scalingFactor = Utils.AsDouble(ScalingFactor.Run(c, tags) ?? 1.0, "scalingfactor");
weightExplanation.Add("Scaling factor: " + scalingFactor);
priority *= scalingFactor;
if (priority <= 0)
{
canAccess = "no";
@ -257,7 +234,7 @@ namespace AspectedRouting.Language.Expression
}
else
{
throw new Exception("CanAccess or oneway are not strings but " + canAccess.GetType().ToString() +
throw new Exception("CanAccess or oneway are not strings but " + canAccess.GetType() +
" and " + (oneway?.GetType()?.ToString() ?? "<null>"));
}
}