More typesystem fixes, atleast now properly works

This commit is contained in:
Pieter Vander Vennet 2020-06-17 17:23:48 +02:00
parent 173756818e
commit 57704f5ee5
21 changed files with 262 additions and 88 deletions

View file

@ -329,12 +329,17 @@ namespace AspectedRouting.Test
[Fact] [Fact]
public void SpecializeToCommonType() public void SpecializeToCommonType()
{ {
var p0 = Funcs.Parse; var p0 = Funcs.Parse.Specialize(new Curry(Typs.String, Typs.PDouble));
var p1 = Funcs.Const.Apply(new Constant(1.0)); var p1 = Funcs.Const.Apply(new Constant(1.0)).Specialize(
new Curry(new Var("a"), Typs.Double));
var exprs = new[] {p0, p1}; var exprs = new[] {p0, p1};
var newTypes = exprs.SpecializeToCommonTypes(out var specializedExpressions); var newTypes = exprs.SpecializeToCommonTypes(out var _);
Assert.Single(newTypes); Assert.Single( newTypes);
exprs = new[] {p1, p0};
newTypes = exprs.SpecializeToCommonTypes(out var _);
Assert.Single( newTypes);
} }
} }
} }

View file

@ -25,7 +25,7 @@ namespace AspectedRouting.Test
{"ferry", "yes"} {"ferry", "yes"}
}; };
Assert.Equal("tags -> double", string.Join(", ", aspect.Types)); Assert.Equal("tags -> pdouble", string.Join(", ", aspect.Types));
Assert.Equal(42d, new Apply(aspect, new Constant(tags)).Evaluate(null)); Assert.Equal(42d, new Apply(aspect, new Constant(tags)).Evaluate(null));
} }

View file

@ -1,9 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=af5d2251_002D713d_002D473f_002D9157_002D89c9d06216e5/@EntryIndexedValue">&lt;SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from &amp;lt;AspectedRouting.Test&amp;gt;" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt; <s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=acd4e5d9_002D8d57_002D4495_002Da7aa_002D38598b9e98e0/@EntryIndexedValue">&lt;SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from &amp;lt;AspectedRouting.Test&amp;gt;" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
&lt;Project Location="/home/pietervdvn/werk/AspectedRouting/AspectedRouting.Test" Presentation="&amp;lt;AspectedRouting.Test&amp;gt;" /&gt; &lt;Project Location="/home/pietervdvn/werk/AspectedRouting/AspectedRouting.Test" Presentation="&amp;lt;AspectedRouting.Test&amp;gt;" /&gt;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=bad1d05d_002Df895_002D4e7d_002Da6e2_002Dede32f077b26/@EntryIndexedValue">&lt;SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="SpecializeToCommonType" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;
&lt;TestAncestor&gt;
&lt;TestId&gt;xUnit::A1309041-8AAE-42D7-A886-94C9FFC6A28C::.NETCoreApp,Version=v3.1::AspectedRouting.Test.FunctionsTest.SpecializeToCommonType&lt;/TestId&gt;
&lt;/TestAncestor&gt;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary> &lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>

View file

@ -169,6 +169,7 @@ namespace AspectedRouting.IO.LuaSkeleton
return called.Name; return called.Name;
} }
AddDependenciesFor(called);
AddFunction(called); AddFunction(called);
return $"{fc.CalledFunctionName.AsLuaIdentifier()}(parameters, tags, result)"; return $"{fc.CalledFunctionName.AsLuaIdentifier()}(parameters, tags, result)";
case Constant c: case Constant c:

View file

@ -60,9 +60,8 @@ namespace AspectedRouting.IO.itinero1
var exprInLua = _skeleton.ToLua(expression.Optimize()); var exprInLua = _skeleton.ToLua(expression.Optimize());
var subs = new Curry(Typs.Tags, new Var(("a"))).UnificationTable(expression.Types.First()); var resultTypes = expression.Types.Select(t => t.Uncurry().Last());
if (subs != null && subs.TryGetValue("$a", out var resultType) && if (resultTypes.Any(t => t.Name.Equals(Typs.Bool.Name)))
(resultType.Equals(Typs.Bool) || resultType.Equals(Typs.String)))
{ {
_skeleton. AddDep("parse"); _skeleton. AddDep("parse");
exprInLua = "parse(" + exprInLua + ")"; exprInLua = "parse(" + exprInLua + ")";

View file

@ -0,0 +1,6 @@
function atleast(minimumExpected, actual, thn, els)
if (minimumExpected <= actual) then
return thn;
end
return els
end

View file

@ -197,13 +197,8 @@ namespace AspectedRouting.Language
public static string TypeBreakdown(this IExpression e) public static string TypeBreakdown(this IExpression e)
{ {
var text = "";
e.Visit(x => return e.ToString() + " : "+string.Join(" ; ", e.Types);
{
text += $"\n\n{x}\n : {string.Join("\n : ", x.Types)}";
return true;
});
return text;
} }
public static void SanityCheckProfile(this ProfileMetaData pmd, Context context) public static void SanityCheckProfile(this ProfileMetaData pmd, Context context)

View file

@ -83,14 +83,15 @@ namespace AspectedRouting.Language.Expression
{ {
try try
{ {
_debugInfo = $"\n{f.Optimize().TypeBreakdown()}\n" + _debugInfo = $"\n{f.Optimize().TypeBreakdown().Indent()}\n" +
$"is applied on an argument with types:" + $"is given the argument: " +
$"{string.Join(", ", argument.Optimize().Types)}"; "(" + argument.Optimize().TypeBreakdown() + ")";
} }
catch (Exception) catch (Exception)
{ {
_debugInfo = $"\n{f.TypeBreakdown()}\n" + _debugInfo =$"\n (NO OPT) {f.TypeBreakdown().Indent()}\n" +
$"{argument.TypeBreakdown()}"; $"is given the argument: " +
"(" + argument.TypeBreakdown() + ")";
} }
} }
} }
@ -197,6 +198,7 @@ namespace AspectedRouting.Language.Expression
if (Types.Count() > 1) if (Types.Count() > 1)
{ {
// Too much types to optimize
var optimized = new Dictionary<Type, (IExpression f, IExpression a)>(); var optimized = new Dictionary<Type, (IExpression f, IExpression a)>();
foreach (var (resultType, (f, a)) in FunctionApplications) foreach (var (resultType, (f, a)) in FunctionApplications)
{ {
@ -209,6 +211,7 @@ namespace AspectedRouting.Language.Expression
} }
{ {
// id a => a
var arg = new List<IExpression>(); var arg = new List<IExpression>();
if ( if (
Deconstruct.UnApplyAny( Deconstruct.UnApplyAny(
@ -220,6 +223,37 @@ namespace AspectedRouting.Language.Expression
} }
} }
{
// ifdotted fcondition fthen felse arg => if (fcondition arg) (fthen arg) (felse arg)
var fcondition = new List<IExpression>();
var fthen = new List<IExpression>();
var felse = new List<IExpression>();
var arg = new List<IExpression>();
if (
Deconstruct.UnApplyAny(
Deconstruct.UnApply(
Deconstruct.UnApply(
Deconstruct.UnApply(
Deconstruct.IsFunc(Funcs.IfDotted),
Deconstruct.Assign(fcondition)),
Deconstruct.Assign(fthen)),
Deconstruct.Assign(felse)),
Deconstruct.Assign(arg)
).Invoke(this))
{
var a = arg.First();
return
Funcs.If.Apply(
fcondition.First().Apply(a),
fthen.First().Apply(a),
felse.First().Apply(a)
);
}
}
{ {
var (f, a) = FunctionApplications.Values.First(); var (f, a) = FunctionApplications.Values.First();

View file

@ -158,6 +158,11 @@ namespace AspectedRouting.Language.Expression
priority += aspectInfluence * aspectWeight; priority += aspectInfluence * aspectWeight;
} }
if (priority <= 0)
{
canAccess = "no";
}
return new ProfileResult((string) canAccess, (string) oneway, speed, priority, return new ProfileResult((string) canAccess, (string) oneway, speed, priority,
string.Join("\n ", weightExplanation)); string.Join("\n ", weightExplanation));
} }

View file

@ -45,18 +45,27 @@ namespace AspectedRouting.Language.Functions
public override object Evaluate(Context c, params IExpression[] arguments) public override object Evaluate(Context c, params IExpression[] arguments)
{ {
var minimum = arguments[0].Evaluate(c); var minimum = arguments[0].Evaluate(c);
var f = (IExpression) arguments[1].Evaluate(c);
var then = arguments[2].Evaluate(c); var then = arguments[2].Evaluate(c);
var @else = arguments[3].Evaluate(c); var @else = arguments[3].Evaluate(c);
var x = arguments[4]; var x = arguments[4];
var arg1 = f.Evaluate(c, x); var arg1 = arguments[1].Evaluate(c, x);
if (minimum == null || arg1 == null) if (minimum == null || arg1 == null)
{ {
return null; return null;
} }
if (minimum is IExpression e)
{
minimum = e.Evaluate(c);
}
if (arg1 is IExpression e1)
{
arg1 = e1.Evaluate(c);
}
if (minimum is int i0) if (minimum is int i0)
{ {
minimum = (double) i0; minimum = (double) i0;

View file

@ -18,6 +18,10 @@ namespace AspectedRouting.Language.Functions
if (o is IEnumerable<IExpression> enumerable) if (o is IEnumerable<IExpression> enumerable)
{ {
o = enumerable.ToList(); o = enumerable.ToList();
if (enumerable.Any(x => x == null))
{
throw new NullReferenceException("Some subexpression is null");
}
} }
_o = o; _o = o;
@ -29,6 +33,10 @@ namespace AspectedRouting.Language.Functions
if (o is IEnumerable<IExpression> enumerable) if (o is IEnumerable<IExpression> enumerable)
{ {
o = enumerable.ToList(); o = enumerable.ToList();
if (enumerable.Any(x => x == null))
{
throw new NullReferenceException("Some subexpression is null");
}
} }
_o = o; _o = o;
@ -39,6 +47,10 @@ namespace AspectedRouting.Language.Functions
var tps = exprs var tps = exprs
.SpecializeToCommonTypes(out var specializedVersions) .SpecializeToCommonTypes(out var specializedVersions)
.Select(t => new ListType(t)); .Select(t => new ListType(t));
if(specializedVersions.Any(x => x == null))
{
throw new Exception("Specializing to common types failed for "+string.Join("," ,exprs.Select(e => e.ToString())));
}
Types = tps.ToList(); Types = tps.ToList();
_o = specializedVersions; _o = specializedVersions;
} }
@ -49,6 +61,10 @@ namespace AspectedRouting.Language.Functions
{ {
Types = exprs Types = exprs
.SpecializeToCommonTypes(out var specializedVersions).Select(t => new ListType(t)).ToList(); .SpecializeToCommonTypes(out var specializedVersions).Select(t => new ListType(t)).ToList();
if (specializedVersions.Any(x => x == null))
{
throw new NullReferenceException("Some subexpression is null");
}
_o = specializedVersions.ToList(); _o = specializedVersions.ToList();
} }
catch (Exception e) catch (Exception e)

View file

@ -8,9 +8,10 @@ namespace AspectedRouting.Language.Functions
{ {
public class Dot : Function public class Dot : Function
{ {
public override string Description { get; } = "Higher order function: converts `f (g a)` into `(dot f g) a`. In other words, this fuses `f` and `g` in a new function, which allows the argument to be lifted out of the expression "; public override string Description { get; } =
"Higher order function: converts `f (g a)` into `(dot f g) a`. In other words, this fuses `f` and `g` in a new function, which allows the argument to be lifted out of the expression ";
public override List<string> ArgNames { get; } = new List<string>{"f","g","a"}; public override List<string> ArgNames { get; } = new List<string> {"f", "g", "a"};
public static readonly Var A = new Var("a"); public static readonly Var A = new Var("a");
public static readonly Var B = new Var("b"); public static readonly Var B = new Var("b");
public static readonly Var C = new Var("c"); public static readonly Var C = new Var("c");
@ -33,6 +34,10 @@ namespace AspectedRouting.Language.Functions
public override object Evaluate(Context c, params IExpression[] arguments) public override object Evaluate(Context c, params IExpression[] arguments)
{ {
if (arguments.Count() <= 2)
{
}
var f0 = arguments[0]; var f0 = arguments[0];
var f1 = arguments[1]; var f1 = arguments[1];
var resultType = ((Curry) f1.Types.First()).ResultType; var resultType = ((Curry) f1.Types.First()).ResultType;

View file

@ -38,8 +38,7 @@ namespace AspectedRouting.Language
/// </summary> /// </summary>
/// <param name="argument"></param> /// <param name="argument"></param>
/// <returns></returns> /// <returns></returns>
// IExpression OptimizeWithArgument(IExpression argument); // IExpression OptimizeWithArgument(IExpression argument);
void Visit(Func<IExpression, bool> f); void Visit(Func<IExpression, bool> f);
} }
@ -47,7 +46,7 @@ namespace AspectedRouting.Language
{ {
public static object Run(this IExpression e, Context c, Dictionary<string, string> tags) public static object Run(this IExpression e, Context c, Dictionary<string, string> tags)
{ {
return e.Apply(new []{new Constant(tags)}).Evaluate(c); return e.Apply(new[] {new Constant(tags)}).Evaluate(c);
} }
public static IExpression Specialize(this IExpression e, Type t) public static IExpression Specialize(this IExpression e, Type t)
@ -101,8 +100,11 @@ namespace AspectedRouting.Language
out IEnumerable<Type> specializedTypes, out IEnumerable<IExpression> specializedExpressions) out IEnumerable<Type> specializedTypes, out IEnumerable<IExpression> specializedExpressions)
{ {
specializedTypes = null; specializedTypes = null;
var expressions = exprs.ToList(); var exprsForTypes = exprs.SortWidestToSmallest();
foreach (var f in expressions) exprsForTypes.Reverse();
foreach (var f in exprsForTypes)
{ {
if (specializedTypes == null) if (specializedTypes == null)
{ {
@ -110,9 +112,7 @@ namespace AspectedRouting.Language
continue; continue;
} }
// TODO FIXME var specialized = f.Types.RenameVars(specializedTypes).SpecializeTo(specializedTypes, false);
// EITHER THE TYPES HAVE TO BE FROM SPECIFIC TO NON-SPECIFIC ORDER OR VICE VERSA
var specialized = f.Types.RenameVars(specializedTypes).SpecializeTo(specializedTypes);
// ReSharper disable once JoinNullCheckWithUsage // ReSharper disable once JoinNullCheckWithUsage
if (specialized == null) if (specialized == null)
{ {
@ -126,7 +126,15 @@ namespace AspectedRouting.Language
} }
var tps = specializedTypes; var tps = specializedTypes;
return specializedExpressions = expressions.Select(expr => expr.Specialize(tps));
var optExprs = new List<IExpression>();
foreach (var expr in exprs)
{
var exprOpt = expr.Specialize(tps);
optExprs.Add(exprOpt);
}
return specializedExpressions = optExprs;
} }
} }
} }

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -23,7 +24,7 @@ namespace AspectedRouting.Language.Typ
} }
public static HashSet<Type> SpecializeTo(this IEnumerable<Type> types0, IEnumerable<Type> allowedTypes) public static HashSet<Type> SpecializeTo(this IEnumerable<Type> types0, IEnumerable<Type> allowedTypes, bool reverseSuperSet = true)
{ {
var results = new HashSet<Type>(); var results = new HashSet<Type>();
@ -32,7 +33,7 @@ namespace AspectedRouting.Language.Typ
{ {
foreach (var allowed in allowedTypes) foreach (var allowed in allowedTypes)
{ {
var unified = t0.Unify(allowed, true); var unified = t0.Unify(allowed, reverseSuperSet);
if (unified != null) if (unified != null)
{ {
results.Add(unified); results.Add(unified);
@ -70,9 +71,10 @@ namespace AspectedRouting.Language.Typ
{ {
return SelectSmallestUnion(t1, subbed); return SelectSmallestUnion(t1, subbed);
} }
return SelectSmallestUnion(subbed, t1); return SelectSmallestUnion(subbed, t1);
} }
private static Type SelectSmallestUnion(this Type wider, Type smaller, bool reverse = false) private static Type SelectSmallestUnion(this Type wider, Type smaller, bool reverse = false)
{ {
switch (wider) switch (wider)
@ -99,6 +101,81 @@ namespace AspectedRouting.Language.Typ
} }
} }
public static List<IExpression> SortWidestToSmallest(this IEnumerable<IExpression> expressions)
{
var all = expressions.ToHashSet();
var sorted = new List<IExpression>();
while (all.Any())
{
var widest = SelectWidestType(all);
if (widest == null)
{
throw new ArgumentException("Can not sort widest to smallest");
}
all.Remove(widest);
sorted.Add(widest);
}
return sorted;
}
public static IExpression SelectSmallestType(IEnumerable<IExpression> expressions)
{
IExpression smallest = null;
foreach (var current in expressions)
{
if (smallest == null)
{
smallest = current;
continue;
}
if (smallest.Types.AllAreSuperset(current.Types))
{
smallest = current;
}
}
return smallest;
}
public static IExpression SelectWidestType(IEnumerable<IExpression> expressions)
{
IExpression widest = null;
foreach (var current in expressions)
{
if (widest == null)
{
widest = current;
continue;
}
if (current.Types.AllAreSuperset(widest.Types))
{
widest = current;
}
}
return widest;
}
public static bool AllAreSuperset(this IEnumerable<Type> shouldBeSuper, IEnumerable<Type> shouldBeSmaller)
{
foreach (var super in shouldBeSuper)
{
foreach (var smaller in shouldBeSmaller)
{
if (!super.IsSuperSet(smaller))
{
return false;
}
}
}
return true;
}
/// <summary> /// <summary>
/// Tries to unify t0 with all t1's. /// Tries to unify t0 with all t1's.
/// Every match is returned /// Every match is returned
@ -136,7 +213,6 @@ namespace AspectedRouting.Language.Typ
} }
public static Type Substitute(this Type t0, Dictionary<string, Type> substitutions) public static Type Substitute(this Type t0, Dictionary<string, Type> substitutions)
{ {
switch (t0) switch (t0)
@ -161,7 +237,8 @@ namespace AspectedRouting.Language.Typ
/// <param name="t0"></param> /// <param name="t0"></param>
/// <param name="t1"></param> /// <param name="t1"></param>
/// <returns></returns> /// <returns></returns>
public static Dictionary<string, Type> UnificationTable(this Type t0, Type t1, bool reverseSupersetRelation = false) public static Dictionary<string, Type> UnificationTable(this Type t0, Type t1,
bool reverseSupersetRelation = false)
{ {
var substitutionsOn0 = new Dictionary<string, Type>(); var substitutionsOn0 = new Dictionary<string, Type>();
@ -235,7 +312,7 @@ namespace AspectedRouting.Language.Typ
AddSubs(v.Name, t0); AddSubs(v.Name, t0);
break; break;
} }
if (!reverseSupersetRelation && !t0.IsSuperSet(t1)) if (!reverseSupersetRelation && !t0.IsSuperSet(t1))
{ {
return null; return null;
@ -281,6 +358,11 @@ namespace AspectedRouting.Language.Typ
public static bool IsSuperSet(this Type t0, Type t1) public static bool IsSuperSet(this Type t0, Type t1)
{ {
if (t0 is Var || t1 is Var)
{
return true;
}
switch (t0) switch (t0)
{ {
case StringType _ when t1 is BoolType _: case StringType _ when t1 is BoolType _:

View file

@ -21,7 +21,7 @@ namespace AspectedRouting
foreach (var file in jsonFileNames) foreach (var file in jsonFileNames)
{ {
var fi = new FileInfo(file); var fi = new FileInfo(file);
var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name); var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name);
if (aspect == null) continue; if (aspect == null) continue;
@ -63,11 +63,6 @@ namespace AspectedRouting
var result = new List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)>(); var result = new List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)>();
foreach (var jsonFile in jsonFiles) foreach (var jsonFile in jsonFiles)
{ {
if (!jsonFile.Contains("bicycle"))
{
continue;
}
try try
{ {
var profile = var profile =
@ -227,6 +222,7 @@ namespace AspectedRouting
// With everything parsed and typechecked, time for tests // With everything parsed and typechecked, time for tests
var testsOk = true;
foreach (var (aspect, t) in aspects) foreach (var (aspect, t) in aspects)
{ {
if (t == null) if (t == null)
@ -235,18 +231,27 @@ namespace AspectedRouting
} }
else else
{ {
t.Run(); testsOk &= t.Run();
} }
} }
foreach (var (profile, profileTests) in profiles) foreach (var (profile, profileTests) in profiles)
{ {
foreach (var test in profileTests) foreach (var test in profileTests)
{ {
test.Run(context); testsOk &= test.Run(context);
} }
}
if (!testsOk)
{
Console.WriteLine("Some tests failed, quitting now without generating output");
return;
}
foreach (var (profile, profileTests) in profiles)
{
PrintUsedTags(profile, context); PrintUsedTags(profile, context);
var aspectTests = aspects.Select(a => a.tests).ToList(); var aspectTests = aspects.Select(a => a.tests).ToList();

View file

@ -61,7 +61,7 @@ namespace AspectedRouting.Tests
public void Run() public bool Run()
{ {
var failed = false; var failed = false;
var testCase = 0; var testCase = 0;
@ -88,12 +88,9 @@ namespace AspectedRouting.Tests
} }
} }
if (failed)
{
throw new ArgumentException("Some test failed");
}
Console.WriteLine($"[{FunctionToApply.Name}] {testCase} tests successful"); Console.WriteLine($"[{FunctionToApply.Name}] {testCase} tests " + (failed ? "failed" : "successful"));
return !failed;
} }
} }
} }

View file

@ -77,8 +77,7 @@ namespace AspectedRouting.Tests
weight = double.Parse(testData[3]); weight = double.Parse(testData[3]);
} }
var expected = new ProfileResult( var expected = new ProfileResult(
testData[0], testData[0],
testData[1], testData[1],
@ -88,9 +87,10 @@ namespace AspectedRouting.Tests
if (expected.Priority == 0 && expected.Access != "no") if (expected.Priority == 0 && expected.Access != "no")
{ {
throw new ArgumentException("A priority of zero is interpreted as 'no access' - don't use it"); throw new ArgumentException(
"A priority of zero is interpreted as 'no access' - don't use it");
} }
var vals = testData.GetRange(4, testData.Count - 4); var vals = testData.GetRange(4, testData.Count - 4);
var tags = new Dictionary<string, string>(); var tags = new Dictionary<string, string>();
for (int i = 0; i < keys.Count; i++) for (int i = 0; i < keys.Count; i++)
@ -192,11 +192,8 @@ namespace AspectedRouting.Tests
return success; return success;
} }
public void Run(Context c) public bool Run(Context c)
{ {
var allOk = true; var allOk = true;
var i = 1; var i = 1;
foreach (var (expected, tags) in Tests) foreach (var (expected, tags) in Tests)
@ -213,14 +210,9 @@ namespace AspectedRouting.Tests
i++; i++;
} }
if (!allOk) Console.WriteLine($"[{Profile.Name}] {Tests.Count()} tests " + (allOk ? "successfull" : "executed, some failed") +
{ $" for behaviour {BehaviourName}");
throw new ArgumentException("Some tests failed for " + BehaviourName); return allOk;
}
else
{
Console.WriteLine($"[{Profile.Name}] {Tests.Count()} tests successful for behaviour {BehaviourName}");
}
} }
} }
} }

View file

@ -39,7 +39,17 @@
"#timeNeeded": "$speed", "#timeNeeded": "$speed",
"#distance": "$distance", "#distance": "$distance",
"#trespassingPenalty": "$clean_permission_score", "#trespassingPenalty": "$clean_permission_score",
"#leastSafetyPenalty": 0 "#leastSafetyPenalty": {
"$multiply": [
"$speed",
{
"$atleast": "#leastSafetyRequired",
"f": "$bicycle.safety",
"then": 0,
"else": -1
}
]
}
}, },
"defaults": { "defaults": {
"#defaultSpeed": 15, "#defaultSpeed": 15,
@ -56,16 +66,18 @@
"#trespassingPenalty": 15, "#trespassingPenalty": 15,
"#": "This is not a priority weight, but rather a kind of access restriction. If 'leastafety' is not met, a huge penalty is applied, namely #leastSafetyPenalty. Note: 0.1 is the safety level of a primary without cycle highway", "#": "This is not a priority weight, but rather a kind of access restriction. If 'leastafety' is not met, a huge penalty is applied, namely #leastSafetyPenalty. Note: 0.1 is the safety level of a primary without cycle highway",
"#leastSafetyRequired": 0.11, "#leastSafetyRequired": 0.11,
"#leastSafetyPenalty": 2 "#leastSafetyPenalty": 0
}, },
"behaviours": { "behaviours": {
"fastest": { "fastest": {
"description": "The fastest route to your destination", "description": "The fastest route to your destination",
"#timeNeeded": 1 "#timeNeeded": 1,
"#leastSafetyPenalty": 2
}, },
"shortest": { "shortest": {
"description": "The shortest route, independent of of speed", "description": "The shortest route, independent of of speed",
"#distance": 1 "#distance": 1,
"#leastSafetyPenalty": 2
}, },
"safety": { "safety": {
"description": "A defensive route shying away from big roads with lots of cars", "description": "A defensive route shying away from big roads with lots of cars",
@ -73,7 +85,8 @@
}, },
"comfort": { "comfort": {
"description": "A comfortable route preferring well-paved roads, smaller roads and a bit of scenery at the cost of speed", "description": "A comfortable route preferring well-paved roads, smaller roads and a bit of scenery at the cost of speed",
"#comfort": 1 "#comfort": 1,
"#leastSafetyPenalty": 2
}, },
"comfort_safety": { "comfort_safety": {
"description": "A route which aims to be both safe and comfortable at the cost of speed", "description": "A route which aims to be both safe and comfortable at the cost of speed",
@ -84,7 +97,8 @@
"description": "A profile for a bike with an electrical motor where the engine doesn't go faster then 25km/h (thus NOT the speed-pedelec). This is a variation of the normal fastest, but with a faster default speed. As the maxspeed is 30, it'll resemble shortest a bit more on 'normal' streets and will penalize slower roads more", "description": "A profile for a bike with an electrical motor where the engine doesn't go faster then 25km/h (thus NOT the speed-pedelec). This is a variation of the normal fastest, but with a faster default speed. As the maxspeed is 30, it'll resemble shortest a bit more on 'normal' streets and will penalize slower roads more",
"#defaultSpeed": 23, "#defaultSpeed": 23,
"#maxspeed": 30, "#maxspeed": 30,
"#timeNeeded": 1 "#timeNeeded": 1,
"#leastSafetyPenalty": 2
}, },
"networks": { "networks": {
"description": "A recreative route following any existing cycling network. Might make a few detours", "description": "A recreative route following any existing cycling network. Might make a few detours",
@ -111,7 +125,8 @@
"cycle_highway": { "cycle_highway": {
"description": "A route preferring the 'cycle-highways'. On non-cycleways, fastest is used (with a very low factor) in order to make sure the behaviour there is defined ", "description": "A route preferring the 'cycle-highways'. On non-cycleways, fastest is used (with a very low factor) in order to make sure the behaviour there is defined ",
"#cycleHighwayNetworkScore": 20, "#cycleHighwayNetworkScore": 20,
"#timeNeeded": 0.1 "#timeNeeded": 0.1,
"#leastSafetyPenalty": 2
}, },
"node_network": { "node_network": {
"description": "A route following the recreational node network. Might make detours", "description": "A route following the recreational node network. Might make detours",

View file

@ -27,9 +27,14 @@
"speed":{ "speed":{
"$min": "$min":
[ [
{"$multiply":["#defaultSpeed", "$bicycle.speed_factor"]}, "#maxspeed",
"$legal_maxspeed_be", "$legal_maxspeed_be",
"#maxspeed" {
"$multiply": [
"#defaultSpeed",
"$bicycle.speed_factor"
]
}
] ]
}, },
"access":"$speedPedelec.access_be", "access":"$speedPedelec.access_be",

View file

@ -1,8 +1,8 @@
access,oneway,speed,priority,highway,bicycle,surface,cycleway:left,oneway,oneway:bicycle,access,maxspeed,junction access,oneway,speed,priority,highway,bicycle,surface,cycleway:left,oneway,oneway:bicycle,access,maxspeed,junction
no,both,0,0,,,,,,,,, no,both,0,0,,,,,,,,,
designated,both,15,15,cycleway,,,,,,,, designated,both,15,15,cycleway,,,,,,,,
yes,both,15,15,primary,,,,,,,, no,both,15,-15,primary,,,,,,,,
yes,both,15,15,primary,yes,,,,,,, no,both,15,-15,primary,yes,,,,,,,
yes,both,15,15,residential,,,,,,,, yes,both,15,15,residential,,,,,,,,
yes,both,13.5,13.5,residential,yes,sett,,,,,, yes,both,13.5,13.5,residential,yes,sett,,,,,,
dismount,both,2.25,2.25,pedestrian,,,,,,,, dismount,both,2.25,2.25,pedestrian,,,,,,,,

1 access oneway speed priority highway bicycle surface cycleway:left oneway oneway:bicycle access maxspeed junction
2 no both 0 0
3 designated both 15 15 cycleway
4 yes no both 15 15 -15 primary
5 yes no both 15 15 -15 primary yes
6 yes both 15 15 residential
7 yes both 13.5 13.5 residential yes sett
8 dismount both 2.25 2.25 pedestrian

View file

@ -2,4 +2,4 @@ access,oneway,speed,priority,highway,surface
no,both,0,0,, no,both,0,0,,
designated,both,15,1,cycleway, designated,both,15,1,cycleway,
yes,both,5.25,1,path,ground yes,both,5.25,1,path,ground
yes,both,15,1,primary, no,both,15,-29,primary,

1 access oneway speed priority highway surface
2 no both 0 0
3 designated both 15 1 cycleway
4 yes both 5.25 1 path ground
5 yes no both 15 1 -29 primary