/// <summary> Adds the specified set such that its relations are tracked. </summary> public void Add(Set set) { Contract.Requires(set != null); Contract.Requires(!relations.ContainsKey(set)); Contract.RequiresForAll(relations.Values, value => !value.ContainsKey(set)); Contract.Requires(set != DefaultNotions.EmptySet, "The empty set should not be added via this method"); Contract.Requires(relations.Keys.Contains(DefaultNotions.EmptySet), "The empty set should already be in this set relations before adding anything. "); //Creates a new entry for all existing sets: foreach (var dict in relations) dict.Value.Add(set, SetRelationType.Unknown); //creates the new relations for the set: Dictionary<Set, SetRelationType> dictionaryRelationToSet = this.Sets.ToDictionary<Set, SetRelationType>(_ => SetRelationType.Unknown, GloballyScopedMethods.ReferenceEqualityComparer); dictionaryRelationToSet.Add(set, SetRelationType.Subset); //explicitly sets the correct relations for the empty set: dictionaryRelationToSet[DefaultNotions.EmptySet] = SetRelationType.Disjoint; relations[DefaultNotions.EmptySet][set] = SetRelationType.Subset; //incorporate the addedum in this instance: relations.Add(set, dictionaryRelationToSet); CheckConsistency(); }
/// <summary> Gets or sets the relation between the two specified sets, and updates all other sets consequentially. </summary> internal SetRelationType this[Set containee, Set container] { get { return relations[containee][container]; } private set { Contract.Requires(relations.ContainsKey(containee)); Contract.Requires(relations.ContainsKey(container)); Contract.RequiresEnumIsDefined(value); switch (value) { case SetRelationType.Unknown: throw new ArgumentOutOfRangeException("You cannot specify the unknown relation. Always provide information. "); case SetRelationType.Overlap: AddOverlapRelation(containee, container); break; case SetRelationType.Disjoint: AddNoOverlapRelation(containee, container); break; case SetRelationType.Subset: AddSubsetRelation(containee, container); break; default: throw new Exception(); } } }
/// <param name="superset"> Cannot be null. </param> public VariableSet(Set superset, string description = null) : base(superset.Domain ?? DefaultNotions.OverarchingSet, description ?? $"var<{superset.Description}>", isVariable: true) { Contract.Requires(superset != null); Superset = superset; //what is the difference between a variable set's superset and its domain? //A variable set means that it represents any set in its superset. Hence, it is an element of the set of which the superset is an element }
public override bool Contains(Notion element, Set set) { //an element e could be found to be in some set S //- if the set that contains e is a (proper) subset of S //- if e is known to be in S by an enumeration rule return set.Supersets(element.Domain) || enumerationRelations.Contains(element, set); }
public override bool Subsets(Set containee, Set container) { Contract.Requires(containee != null); Contract.Requires(container != null); Contract.Requires(containee.IsConstant, "Set relations only pertain to constant sets"); Contract.Requires(container.IsConstant, "Set relations only pertain to constant sets"); return SetRelations.Subsets(containee, container); }
public override void Append(Notion element, Set set) { Contract.Requires(element != null); Contract.Requires(set != null); Contract.Requires(set.IsAppendable); Contract.Requires(set.IsConstant, "You can only append elements to constant sets"); enumerationRelations.Append(element, set); }
/// <summary> Creates a new set relation. </summary> /// <param name="leftOperand"> The first set in the relation (order only matters for the containment relation, in which case this is the smaller (or equal) set). </param> /// <param name="rightOperand"> The second set in the relation (order only matters for the containment relation, in which case this is the larger (or equal) set).</param> /// <param name="relation"> The relation conveyed by this instance that the two specified sets have. </param> public SetRelation(Set leftOperand, Set rightOperand, SetRelationType relation) { Contract.Requires(leftOperand != null); Contract.Requires(rightOperand != null); Contract.RequiresEnumIsDefined(relation); LeftOperand = leftOperand; RightOperand = rightOperand; Relation = relation; }
public void SetRelationsTest1() { SetRelations relations = new SetRelations(); Set s1 = new Set(workspace, "1", false); Notion n1 = new Notion(s1, "1", true); relations.Add(s1); Contract.Assert(relations.Subsets(EmptySet, s1)); Contract.Assert(relations.Subsets(s1, s1)); }
/// <summary> Adds the specified operator to the respective appendable sets regarding domainKind, associativity and precedence. </summary> public static void Add(Notion @operator, DomainKind domainKind, Associativity associativity, Set precedenceSet) { Contract.Requires(@operator != null); Contract.RequiresEnumIsDefined(domainKind); Contract.Requires(domainKind != DomainKind.Operand); Contract.RequiresEnumIsDefined(associativity); Contract.Requires(precedenceSet != null); Contract.Requires(ReferenceEquals(precedenceSet.Workspace, @operator.Workspace)); Contract.Requires(Precedences.Contains(precedenceSet)); Contract.Requires(AllAppendableSetsRelationToLinearNotions.All(linearAppendableSet => !linearAppendableSet.Contains(@operator))); Contract.Requires(precedenceSet.IsAppendable); var workspace = @operator.Workspace; precedenceSet.Append(@operator); switch (domainKind) { case DomainKind.UnaryPrefix: UnaryPreOperators.Append(@operator); break; case DomainKind.UnaryPostfix: UnaryPostOperators.Append(@operator); break; case DomainKind.Binary: BinaryOperators.Append(@operator); break; case DomainKind.Nullary: NullaryOperators.Append(@operator); break; case DomainKind.Operand: default: throw new Exception(); } switch (associativity) { case Associativity.Left: LeftAssociativeOperators.Append(@operator); break; case Associativity.Right: RightAssociativeOperators.Append(@operator); break; case Associativity.Undefined: UnassociativeOperators.Append(@operator); break; case Associativity.Associative: AssociativeOperators.Append(@operator); break; default: throw new Exception(); } }
public void SetRelationsTest2() { SetRelations relations = new SetRelations(); Set s1 = new Set(workspace, "1"); Notion n1 = new Notion(s1, "1", true); relations.Add(s1); relations.Add(Booleans); Contract.Assert(relations.Subsets(EmptySet, s1)); Contract.Assert(relations.Subsets(s1, s1)); Contract.Assert(relations.Subsets(EmptySet, Booleans)); Contract.Assert(relations.Subsets(Booleans, Booleans)); Contract.Assert(relations.IsUnknown(Booleans, s1)); }
/// <summary> Appends the specified element to the specified set. </summary> public void Append(Notion element, Set set) { Contract.Requires(element != null); Contract.Requires(set != null); Contract.Requires(set.IsAppendable); EnumerationRelation enumeration = TryGetEnumeration(set); if (enumeration == null) { relations.Add(new EnumerationRelation(element.ToSingletonList(), set)); } else { Contract.Assert(enumeration.elements != null, "This shouldn't be null for appendable sets, since this mutable list allows to append elements to the enumeration relation"); Contract.Assert(!enumeration.elements.Contains(element, ReferenceEqualityComparer), "The specified notion is already an element in the set to append it to"); enumeration.elements.Add(element); } }
/// <summary> Tries to find an expression of the form ?∈set, and returns the involved name instance and set. </summary> /// <param name="expression"> The expression that may be of the form ?∈set. </param> /// <param name="toBeDefined"> If the specified expression was of said form, this is the left hand operand. </param> /// <param name="toBeDefinedIn"> If the specified expression was of said form, this is the right hand operand's set. </param> public static bool TryIdentifyDefinition(CompositeNameInstance expression, out NameInstance toBeDefined, out Set toBeDefinedIn) { Contract.Requires(expression != null); if (expression.Elements.Count == 3 && expression.Elements[0].Name == null //first expression element is still unknown && expression.Elements[1].Name?.Notion == DefaultNotions.InDefining && expression.Elements[2].Name?.Notion is Set) { toBeDefined = expression.Elements[0]; toBeDefinedIn = (Set)expression.Elements[2].Name.Notion; return true; } else { toBeDefined = null; toBeDefinedIn = null; return false; } }
public void SetRelationsTest3() { SetRelations relations = new SetRelations(); Set s1 = new Set(workspace, "1"); Notion n1 = new Notion(s1, "1", true); Set s12 = new Set(workspace, "12"); Notion n2 = new Notion(s12, "2", true); relations.Add(s1); relations.Add(s12); relations.AddSubsetRelation(s1, s12); Contract.Assert(relations.Subsets(EmptySet, s1)); Contract.Assert(relations.Subsets(s1, s1)); Contract.Assert(relations.Subsets(EmptySet, s12)); Contract.Assert(relations.Subsets(s12, s12)); Contract.Assert(relations.Subsets(s1, s12)); }
/// <summary> Gets the sets for which it is known that it is a subset of the specified set. </summary> public IEnumerable<Set> GetSubsetsOf(Set superset) { Contract.Requires(superset != null); Contract.Requires(relations.ContainsKey(superset)); Contract.AssertForAll(relations.Values, dict => dict.ContainsKey(superset)); return relations[superset].Where(kvp => kvp.Value == SetRelationType.Subset).Select(kvp => kvp.Key); }
public override ReadOnlyCollection<Notion> TryGetElements(Set set) { return enumerationRelations.TryGetElements(set); }
/// <summary> Creates a nice debugger view for a relation between two sets. </summary> public static string ToString(this SetRelationType relation, Set leftOperand, Set rightOperand) { Contract.RequiresEnumIsDefined(relation); switch (relation) { case SetRelationType.Unknown: return $"{leftOperand} ? {rightOperand}"; case SetRelationType.Disjoint: return $"{leftOperand} ∩ {rightOperand} = ∅"; case SetRelationType.Overlap: return $"{leftOperand} ∩ {rightOperand} ≠ ∅"; case SetRelationType.Subset: return $"{leftOperand} ⊆ {rightOperand}"; default: throw new Exception();//impossible to reach } }
/// <summary> Gets whether the current set is a superset of the specified set. </summary> public virtual bool Supersets(Set set) { Contract.Requires(set != null); //there is very little to deduce about supersetting of non-generic sets (assuming no derived type is calling this) //basically, only a superset can be provided, which the workspace is informed of, so we just delegate this method to the workspace: it knows at least at much as this set return Workspace.Subsets(set, this); }
/// <summary> Defines the specified name instance to be a representation of a new element in the specified set. </summary> public void Add(NameInstance toBeDefined, Set toBeDefinedIn) { var newNotion = new Notion(toBeDefinedIn, "No description available", false); //newNotion.Add(toBeDefined); base.Add(newNotion); }
public override SetRelationType GetRelationBetween(Set lhs, Set rhs) { return SetRelations[lhs, rhs]; }
public void SetRelationsTest7() { SetRelations relations = new SetRelations(); Set s1 = new Set(workspace, "1"); Notion n1 = new Notion(s1, "1", true); Set s12 = new Set(workspace, "12"); Notion n2 = new Notion(s12, "2", true); Set s3 = new Set(workspace, "3"); Notion n3 = new Notion(s3, "3", true); Set s123 = new Set(workspace, "123"); Set true1 = new Set(workspace, "true1"); relations.Add(s1); relations.Add(s12); relations.Add(s3); relations.Add(s123); relations.Add(Booleans); relations.Add(true1); relations.AddSubsetRelation(s1, s12); relations.AddSubsetRelation(s12, s123);//should be able to infer s1 \in s123 relations.AddSubsetRelation(s3, s123); relations.AddOverlapRelation(true1, Booleans); relations.AddSubsetRelation(s1, true1); Contract.Assert(relations.Subsets(s1, s12)); Contract.Assert(relations.Subsets(s1, s123)); Contract.Assert(relations.Subsets(s12, s123)); Contract.Assert(relations.IsUnknown(s12, s3)); Contract.Assert(relations.Intersects(true1, s12));//this one is nice Contract.Assert(relations.Intersects(true1, s123)); Contract.Assert(relations.Intersects(true1, Booleans)); relations.AddNoOverlapRelation(s12, s3); Contract.Assert(relations.Subsets(s1, s12)); Contract.Assert(relations.Subsets(s1, s123)); Contract.Assert(relations.Subsets(s12, s123)); Contract.Assert(relations.Disjoins(s12, s3)); Contract.Assert(relations.Intersects(true1, s12)); Contract.Assert(relations.Intersects(true1, s123)); Contract.Assert(relations.Intersects(true1, Booleans)); }
public override void Add(SetRelationType relation, Set lhs, Set rhs) { Contract.Requires(lhs != null); Contract.Requires(rhs != null); Contract.Requires(lhs.IsConstant); Contract.Requires(rhs.IsConstant); Contract.RequiresEnumIsDefined(relation); SetRelations.Add(lhs, rhs, relation); }
/// <summary> Allows to clone a set. Additional arguments optionally override the clone's properties. </summary> protected Set(Set toClone, string description, bool? appendable) : this(toClone.Workspace, description ?? toClone.Description, appendable ?? toClone.IsAppendable, toClone.Superset) { }
public EnumerationRelation TryGetEnumeration(Set set) { return relations.FirstOrDefault(relation => relation.EnumerableSet == set); }
public ReadOnlyCollection<Notion> TryGetElements(Set set) { return relations.FirstOrDefault(relation => relation.EnumerableSet == set)?.Elements; }
public bool Contains(Notion element, Set set) { return TryGetElements(set).Contains(element) == true; }
/// <summary> Checks whether the two specified sets have the specified relation. Doesn't work for containment. </summary> private bool CheckRelation(Set firstSet, Set secondSet, SetRelationType relation) { Contract.Requires(firstSet != null); Contract.Requires(secondSet != null); Contract.RequiresEnumIsDefined(relation); //allows empty sets if (firstSet == DefaultNotions.EmptySet) return relation == SetRelationType.Subset; if (secondSet == DefaultNotions.EmptySet) return relation == SetRelationType.Disjoint; if (firstSet == DefaultNotions.Unknown) return true; if (secondSet == DefaultNotions.Unknown) return false; bool result = this.relations[firstSet][secondSet] == relation; #if DEBUG if (relation.IsAnyOf(SetRelationType.Unknown, SetRelationType.Disjoint)) { bool otherResult = this.relations[secondSet][firstSet] == relation; Contract.Assert(result == otherResult, "Relation." + relation.ToString() + " isn't stored symmetrically"); } #endif return result; }
public void SetRelationsTest6() { SetRelations relations = new SetRelations(); Set s1 = new Set(workspace, "1"); Notion n1 = new Notion(s1, "1", true); Set s12 = new Set(workspace, "12"); Notion n2 = new Notion(s12, "2", true); Set s3 = new Set(workspace, "3"); Notion n3 = new Notion(s3, "3", true); Set s123 = new Set(workspace, "123"); relations.Add(s1); relations.Add(s12); relations.Add(s3); relations.Add(s123); relations.AddSubsetRelation(s1, s12); relations.AddSubsetRelation(s12, s123); Contract.Assert(relations.Subsets(s1, s12)); Contract.Assert(relations.Subsets(s1, s123)); Contract.Assert(relations.Subsets(s12, s123)); Contract.Assert(relations.IsUnknown(s12, s3)); relations.AddOverlapRelation(s123, s3); Contract.Assert(relations.Subsets(s1, s12)); Contract.Assert(relations.Subsets(s1, s123)); Contract.Assert(relations.Subsets(s12, s123)); Contract.Assert(relations.Intersects(s123, s3)); }
public override void AddEnumerableOrAppendableRule(Set enumerableOrAppendableSet, params Notion[] elements) { Contract.Requires(elements != null); Contract.RequiresForAll(elements, NotNull); Contract.Requires(elements.Select(e => e.Domain).AreEqualByRef()); EnumerationRelation relation; if (enumerableOrAppendableSet.IsAppendable) relation = new EnumerationRelation(elements.ToList(), enumerableOrAppendableSet); else relation = new EnumerationRelation(new ReadOnlyCollection<Notion>(elements), enumerableOrAppendableSet); this.enumerationRelations.Add(relation); }
public override IEnumerable<Set> GetSubsetsof(Set superset) { return setRelations.GetSubsetsOf(superset); }
/// <summary> Creates a binary operator notation for the specified notion. </summary> private static IEnumerable<INotation<TDomain>> CreateOrNotation(Set orNotion) { return LinearNotationFactory.CreateSingle(Booleans, new[] { Booleans, orNotion, Booleans }); }