-
Notifications
You must be signed in to change notification settings - Fork 198
T-wise combinatorial test #837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,26 @@ public static void PopulateAllModuleExprs( | |
{ | ||
test.AssumeExpr = exprVisitor.Visit(context.assumeExpr); | ||
} | ||
|
||
if (context.twise() == null) | ||
{ | ||
test.Twise = test.ParamExprMap.Count; | ||
} | ||
else | ||
{ | ||
if (context.twise().PAIRWISE() != null) | ||
{ | ||
test.Twise = 2; | ||
} else if (context.twise().WISE() != null) | ||
{ | ||
var t = int.Parse(context.twise().IntLiteral().GetText()); | ||
if (!(2 <= t && t <= test.ParamExprMap.Count)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apart from whether t should be allowed to be 1, align this check with the error message (or vice-versa). |
||
{ | ||
throw handler.InvalidTwise(context.twise(), test, t, test.ParamExprMap.Count); | ||
} | ||
test.Twise = t; | ||
} | ||
} | ||
} | ||
|
||
foreach (var test in globalScope.RefinementTests) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,118 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using Plang.Compiler.TypeChecker.AST; | ||
using Plang.Compiler.TypeChecker.AST.Declarations; | ||
|
||
namespace Plang.Compiler.TypeChecker; | ||
|
||
public abstract class ParamAssignment | ||
{ | ||
|
||
public static IEnumerable<IEnumerable<T>> DifferentCombinations<T>(IEnumerable<T> elements, int k) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know there are a few end-to-end script tests, but given the complexity of this logic I suggest having some unit tests which actually verify the results of this code. |
||
{ | ||
var enumerable = elements as T[] ?? elements.ToArray(); | ||
return k == 0 ? [Array.Empty<T>()] | ||
: | ||
enumerable.SelectMany((e, i) => | ||
DifferentCombinations(enumerable.Skip(i + 1), k - 1).Select(c => (new[] {e}).Concat(c))); | ||
} | ||
|
||
private static Dictionary<int, T> EnumerableToIndexDict<T> (IEnumerable<T> l, Func<T, T> f) | ||
{ | ||
return Enumerable.Range(0, l.Count()).Zip(l, (a, b) => new { a, b }).ToDictionary(x => x.a, x => f(x.b)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: extra line after the close brace. |
||
private static Dictionary<int, Dictionary<string, int>> MakeVectorMap(Dictionary<string, int> universe, int twise) | ||
{ | ||
var vectorSet = new HashSet<Dictionary<string, int>>(); | ||
foreach (var param in DifferentCombinations(universe.Select(kv => kv.Key), twise)) | ||
{ | ||
var result = new List<Dictionary<string, int>> { new() }; | ||
foreach (var name in param) | ||
{ | ||
var newResult = new List<Dictionary<string, int>>(); | ||
for (var i = 0; i < universe[name]; i++) | ||
{ | ||
var resultCopy = result.Select(dict => dict.ToDictionary(kv => kv.Key, kv => kv.Value)).ToList(); | ||
foreach (var vector in resultCopy) | ||
{ | ||
vector.Add(name, i); | ||
} | ||
newResult.AddRange(resultCopy); | ||
} | ||
result = newResult; | ||
} | ||
vectorSet.UnionWith(result); | ||
} | ||
return EnumerableToIndexDict(vectorSet, x => x); | ||
} | ||
|
||
private static Dictionary<int, HashSet<int>> MakeAssignmentCoverageMap( | ||
Dictionary<int, Dictionary<string, int>> assignmentMap, | ||
Dictionary<int, Dictionary<string, int>> vectorMap, | ||
List<int> assignments) | ||
{ | ||
var assignmentCoverageMap = new Dictionary<int, HashSet<int>>(); | ||
foreach (var assignment in assignments) | ||
{ | ||
assignmentCoverageMap.Add(assignment, []); | ||
foreach (var kv in vectorMap.Where(kv => kv.Value.All(assignmentMap[assignment].Contains))) | ||
{ | ||
assignmentCoverageMap[assignment].Add(kv.Key); | ||
} | ||
} | ||
return assignmentCoverageMap; | ||
} | ||
|
||
private static List<int> GreedyCoverageExplore(Dictionary<string, int> universe, List<Dictionary<string, int>> assignmentList, int twise) | ||
{ | ||
var assignments = Enumerable.Range(0, assignmentList.Count).ToList(); | ||
if (twise == universe.Count) return assignments; | ||
var vectorMap = MakeVectorMap(universe, twise); | ||
var assignmentMap = EnumerableToIndexDict(assignmentList, x => x); | ||
// Console.WriteLine($"twise({twise})"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to have the various debugging trace code commented out? If we think it will be useful later on, I think a better approach is to move it under a flag so that it can be used more easily and doesn't diverge from the code; otherwise, delete it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have deleted these debugging code in the following commit. |
||
// Console.WriteLine($"assignments({assignments.Count})"); | ||
// Console.WriteLine($"vectorMap({vectorMap.Count})"); | ||
// foreach (var (i, indexDic) in vectorMap) | ||
// { | ||
// Console.WriteLine($"vectorMap: {i}: {string.Join(',', indexDic)}"); | ||
// } | ||
var assignmentCoverageMap = MakeAssignmentCoverageMap(assignmentMap, vectorMap, assignments); | ||
// foreach (var (indexDic, c) in assignmentCoverageMap) | ||
// { | ||
// Console.WriteLine($"Coverage: {string.Join(',', indexDic)} :: {string.Join(',', c)}"); | ||
// } | ||
var obligationSet = vectorMap.Keys.ToHashSet(); | ||
// Console.WriteLine($"init obligationSet: {string.Join(',', obligationSet)}"); | ||
obligationSet.IntersectWith(assignmentCoverageMap.SelectMany(kv => kv.Value)); | ||
// Console.WriteLine($"obligationSet: {string.Join(',', obligationSet)}"); | ||
// foreach (var i in obligationSet) | ||
// { | ||
// Console.WriteLine($"Missing Coverage: {string.Join(',', vectorMap[i])}"); | ||
// } | ||
foreach (var kv in assignmentCoverageMap) | ||
{ | ||
assignmentCoverageMap[kv.Key].IntersectWith(obligationSet); | ||
} | ||
var result = new List<int>(); | ||
while (obligationSet.Count != 0) | ||
{ | ||
var (ass, coverage)= assignmentCoverageMap.MaxBy(kv => kv.Value.Count); | ||
// Console.WriteLine($"Missing Coverage: {string.Join(',', obligationSet)}"); | ||
// Console.WriteLine($"Max one({string.Join(',', ass)}) covers({coverage.Count}) {string.Join(',', coverage)}"); | ||
obligationSet.ExceptWith(coverage); | ||
assignmentCoverageMap.Remove(ass); | ||
foreach (var kv in assignmentCoverageMap) | ||
{ | ||
assignmentCoverageMap[kv.Key].ExceptWith(coverage); | ||
} | ||
result.Add(ass); | ||
} | ||
// Console.WriteLine($"result({result.Count})"); | ||
return result; | ||
} | ||
|
||
private static Dictionary<string, IPExpr> Dic2StrDic(Dictionary<Variable, IPExpr> dic) | ||
{ | ||
var dicAux = new Dictionary<string, IPExpr>(); | ||
|
@@ -56,15 +161,35 @@ public static void IterateAssignments(SafetyTest safety, List<Variable> globalPa | |
{ | ||
// Console.WriteLine($"safety.ParamExpr.Count = {safety.ParamExpr.Count}"); | ||
var indexArr = safety.ParamExprMap.ToList().Zip(Enumerable.Repeat(0, safety.ParamExprMap.Count), (x, y) => (x.Key, y)).ToArray(); | ||
var universe = safety.ParamExprMap.ToDictionary(kv => kv.Key, kv => kv.Value.Count); | ||
var assignmentIndices = new List<Dictionary<string, int>>(); | ||
do | ||
{ | ||
var indexDic = indexArr.ToDictionary(item => item.Item1, item => item.Item2); | ||
var dic = IndexDic2Dic(globalParams, safety.ParamExprMap, indexDic); | ||
// Console.WriteLine($"{string.Join(',', dic.ToList())} |- {safety.AssumeExpr}"); | ||
// Console.WriteLine($"{string.Join(',', dic.ToList())} |- {safety.AssumeExpr} = {ForceBool(Eval(dic, safety.AssumeExpr))}"); | ||
if (!SimpleExprEval.ForceBool(SimpleExprEval.Eval(dic, safety.AssumeExpr))) continue; | ||
// Console.WriteLine($"indexArr: {string.Join(',', indexArr)}"); | ||
f(dic); | ||
if (!SimpleExprEval.ForceBool(SimpleExprEval.Eval(dic, safety.AssumeExpr))) | ||
{ | ||
// Console.WriteLine($"UnSat Assumption: indexArr: {string.Join(',', indexArr)}"); | ||
continue; | ||
} | ||
assignmentIndices.Add(indexDic); | ||
// Console.WriteLine($"Sat Assumption: indexArr: {string.Join(',', indexArr)}"); | ||
} while (Next(indexArr, safety.ParamExprMap)); | ||
|
||
foreach (var i in GreedyCoverageExplore(universe, assignmentIndices, safety.Twise)) | ||
{ | ||
// Console.WriteLine($"Choose {safety.Twise}-wise: indexArr: {string.Join(',', assignmentIndices[i])}"); | ||
f(IndexDic2Dic(globalParams, safety.ParamExprMap, assignmentIndices[i])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess you had been using "f" as the name of the parameter for doing the action, but can you use a more descriptive name? |
||
} | ||
// do | ||
// { | ||
// var indexDic = indexArr.ToDictionary(item => item.Item1, item => item.Item2); | ||
// var dic = IndexDic2Dic(globalParams, safety.ParamExprMap, indexDic); | ||
// // Console.WriteLine($"{string.Join(',', dic.ToList())} |- {safety.AssumeExpr}"); | ||
// // Console.WriteLine($"{string.Join(',', dic.ToList())} |- {safety.AssumeExpr} = {ForceBool(Eval(dic, safety.AssumeExpr))}"); | ||
// if (!SimpleExprEval.ForceBool(SimpleExprEval.Eval(dic, safety.AssumeExpr))) continue; | ||
// // Console.WriteLine($"indexArr: {string.Join(',', indexArr)}"); | ||
// f(dic); | ||
// } while (Next(indexArr, safety.ParamExprMap)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, in t-wise combinatorial tests, t can be specified as [1,n] not [2, n].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can always provide more options to the users, I will additional allow 1-wise test.