Skip to content
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

[WIP] TreeDictionary #6

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ build:
verbosity: minimal

test_script:
- OpenCover.Console.exe -register:user -target:"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\MSTest.exe" -targetargs:"/testcontainer:.\phirSOFT.ConstraintedComparisonTests\bin\Release\phirSOFT.ConstraintedComparisonTests.dll" -output:".\phirSOFT_TopologicalComparisonCoverage.xml"

- OpenCover.Console.exe -register:user -target:"vstest.console" -targetargs:"/logger:Appveyor ""C:\projects\phirsoft-topologicalcomparison\phirSOFT.ConstraintedComparisonTests\bin\Release\phirSOFT.ConstraintedComparisonTests.dll""" -output:".\phirSOFT_TopologicalComparisonCoverage.xml"
- codecov -f "phirSOFT_TopologicalComparisonCoverage.xml"
deploy:
- provider: NuGet
Expand Down
106 changes: 106 additions & 0 deletions phirSOFT.ConstraintedComparison/DirectedGraphNode`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace phirSOFT.TopologicalComparison
{
public class DirectedGraphNode<T> : IDirectedGraphNode<T>
{
private readonly HashSet<DirectedGraphNode<T>> _children;
private readonly HashSet<DirectedGraphNode<T>> _parents;
private int _distance;

internal DirectedGraphNode(T node, bool root = false)
{
Value = node;
Distance = root ? 0 : int.MaxValue;
_children = new HashSet<DirectedGraphNode<T>>();
_parents = new HashSet<DirectedGraphNode<T>>();
}

public int Distance
{
get => _distance;
private set
{
if (_distance == value) return;
var old = _distance;
_distance = value;

foreach (var child in _children)
{
child.UpdateDistance(value, old);
}
}
}

private void AddParent(DirectedGraphNode<T> parent)
{
_parents.Add(parent);
Distance = Math.Min(Distance, parent.Distance + 1);
}

private void RemoveParent(DirectedGraphNode<T> parent)
{
_parents.Remove(parent);
if (_parents.Count > 0)
Distance = _parents.Min(node => node.Distance) + 1;
else
Distance = int.MaxValue;
}

public T Value { get; set; }
public IEnumerable<IDirectedGraphNode<T>> Children => _children.AsEnumerable();
ITreeNode<T> ITreeNode<T>.AddChild(T node)
{
return AddChild(node);
}

public void Detach(ITreeNode<T> child)
{
Detach(child as DirectedGraphNode<T>);
}

public void Attach(ITreeNode<T> child)
{
Attach(child as DirectedGraphNode<T>);
}

IEnumerable<ITreeNode<T>> ITreeNode<T>.Children => Children;

public IDirectedGraphNode<T> AddChild(T node)
{
var newNode = new DirectedGraphNode<T>(node);
Attach(newNode);
return newNode;
}

public void Detach(IDirectedGraphNode<T> child)
{
if (!(child is DirectedGraphNode<T> directedChid))
throw new InvalidOperationException();

_children.Remove(directedChid);
directedChid.RemoveParent(this);
}

public void Attach(IDirectedGraphNode<T> child)
{
if (!(child is DirectedGraphNode<T> directedChid))
throw new InvalidOperationException();

_children.Add(directedChid);
directedChid.AddParent(this);
}

private void UpdateDistance(int distance, int oldDistance)
{
if (oldDistance + 1 == distance && distance > oldDistance)
Distance = _parents.Min(node => node.Distance) + 1;
else
Distance = Math.Min(Distance, distance + 1);
}

public IEnumerable<IDirectedGraphNode<T>> Parents => _parents.AsEnumerable();
}
}
19 changes: 19 additions & 0 deletions phirSOFT.ConstraintedComparison/DirectedGraph`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Text;

namespace phirSOFT.TopologicalComparison
{
public class DirectedGraph<T> : IDirectedGraph<T>
{
private readonly DirectedGraphNode<T> _root;

public DirectedGraph(T rootValue)
{
_root = new DirectedGraphNode<T>(rootValue);
}

ITreeNode<T> ITree<T>.Root => _root;

public IDirectedGraphNode<T> Root => _root;

}
}
11 changes: 11 additions & 0 deletions phirSOFT.ConstraintedComparison/IBidirectionalTreeNode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace phirSOFT.TopologicalComparison
{
public interface IBidirectionalTreeNode<TValue> : ITreeNode<TValue, IBidirectionalTreeNode<TValue>>
{
IBidirectionalTreeNode<TValue> Parent {get;}
}
}
9 changes: 9 additions & 0 deletions phirSOFT.ConstraintedComparison/IDirectedGraphNode`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;

namespace phirSOFT.TopologicalComparison
{
public interface IDirectedGraphNode<T> : ITreeNode<T, IDirectedGraphNode<T>>
{
IEnumerable<IDirectedGraphNode<T>> Parents { get; }
}
}
10 changes: 10 additions & 0 deletions phirSOFT.ConstraintedComparison/IDirectedGraph`1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace phirSOFT.TopologicalComparison
{
/// <summary>
/// Represents a directs cycle free graph.
/// </summary>
public interface IDirectedGraph<T> : ITree<T, IDirectedGraphNode<T>>
{

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ public interface ITreeNode<T>
/// Adds a child to this node.
/// </summary>
/// <param name="node">The value of the node to attach</param>
/// <returns>The new added <see cref="ITreeNode{T}"/>.<returns>
/// <returns>The new added <see cref="ITreeNode{T}"/>.</returns>
ITreeNode<T> AddChild(T node);

/// <summary>
/// Detaches an <see cref="ITreeNode{T}"/> from this node.
/// </summary>
/// <param name="child"/> The node to detach </param>
/// <param name="child"> The node to detach </param>
/// <remarks>
/// The child node has to be an direct child of this node.
/// </remarks>
Expand Down
50 changes: 50 additions & 0 deletions phirSOFT.ConstraintedComparison/ITreeNode`2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Collections.Generic;

namespace phirSOFT.TopologicalComparison
{
/// <summary>
/// Provides an interface for a node in an <see cref="ITree{T}"/>
/// </summary>
/// <typeparam name="TValue">The type of the value stored in the node. </typeparam>
/// <typeparam name="TNode">The type of the nodes.</typeparam>
public interface ITreeNode<TValue, TNode> : ITreeNode<TValue> where TNode : ITreeNode<TValue, TNode>
{
/// <summary>
/// Gets or sets value of the node.
/// </summary>
new TValue Value { get; set; }

/// <summary>
/// Gets all children of this node.
/// </summary>
new IEnumerable<TNode> Children { get; }

/// <summary>
/// Adds a child to this node.
/// </summary>
/// <param name="node">The value of the node to attach</param>
/// <returns>The new added <see cref="ITreeNode{T}"/>.</returns>
new TNode AddChild(TValue node);

/// <summary>
/// Detaches an <see cref="ITreeNode{T}"/> from this node.
/// </summary>
/// <param name="child"> The node to detach </param>
/// <remarks>
/// The child node has to be an direct child of this node.
/// </remarks>
void Detach(TNode child);

/// <summary>
/// Attaches an <see cref="ITreeNode{T}"/> to this node.
/// </summary>
/// <param name="child">
/// The <see cref="ITreeNode{T}"/> to attach.
/// </param>
/// <remarks>
/// The <paramref name="child"/> should not be attached to
/// an other parent.
/// </remarks>
void Attach(TNode child);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace phirSOFT.TopologicalComparison
{
/// <summary>
/// Provides an tree data structure
/// Provides a tree data structure
/// </summary>
public interface ITree<T>
{
Expand Down
14 changes: 14 additions & 0 deletions phirSOFT.ConstraintedComparison/ITree`2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace phirSOFT.TopologicalComparison
{
/// <summary>
/// Provides a tree datastructure with a more specific node type.
/// </summary>
/// <typeparam name="TValue">The type of the values stored in the nodes.</typeparam>
/// <typeparam name="TNode">The type of the nodes</typeparam>
public interface ITree<TValue, out TNode> : ITree<TValue> where TNode : ITreeNode<TValue, TNode>
{
/// <inheritdoc cref="ITree{T}.Root"/>
new TNode Root { get; }
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
namespace phirSOFT.TopologicalComparison
using System;

namespace phirSOFT.TopologicalComparison
{
/// <summary>
/// Provides extension method for the <see cref="ITopologicalComparer"/> and
/// <see cref="ITopologicalComparer{T}"/> interfaces.
/// </summary>
public static class TopologicalComparerProxy
public static class TopologicalComparerExtensions
{
/// <summary>
/// Tries to compare two objects using an <see
/// cref="ITopologicalComparer/">.
/// cref="ITopologicalComparer"/>.
/// </summary>
/// <param name="comparer"> The comparer to use.</param>
/// <param name="lhs">The first object to compare.</param>
Expand Down Expand Up @@ -57,5 +59,12 @@ public static bool TryCompare<T>(this ITopologicalComparer<T> comparer, T lhs, T
result = 0;
return false;
}

public static ITopologicalComparer<TTarget> Map<TSource, TTarget>(this ITopologicalComparer<TSource> comparer,
Func<TTarget, TSource> converter)
{
return TopologicalComparer<TTarget>.Create((x, y) => comparer.Compare(converter(x), converter(y)),
(x, y) => comparer.CanCompare(converter(x), converter(y)));
}
}
}
Loading