入力側で IEnumerable フィードを受け取り、出力側で High/Low Bits を正確に生成する一連のゲートを通過できる非常に単純な論理ゲート シミュレータを作成しました。
アイデアは、メモリ内データベースの配列に格納された値をネットワークの入力に供給するマルチゲート ネットワークに概念を拡張し、論理ゲート ネットワークでシナリオ評価ルールセットを複製することです。仮説は、Rx によって許可されるストリーミング アクションは、検索と配列の反復を回避するタイムリーな方法で 400,000 のシナリオを評価するメカニズムを提供する必要があるというものです。入力の大部分はフィード フォワードのみですが、次のシナリオの決定は前のシナリオからの出力に依存するため、ネットワークからの出力を処理する必要があるものもあります。
ネットワークの出力ストリームを、出力がネットワークの出力の解像度の一部であるゲートへの入力ストリームとして使用しようとするネットワークでフィードバック ループを作成しようとするまで、すべて正常に動作します。
出力ストリームを取得して、この方法で使用する方法を知りたいです。「Reactive Extensions の Recursive / fan-out」を見てみると、役立つかもしれませんが、私は Rx に非常に慣れていないため、完全には理解していませんでした。
ここに私がこれまでに持っているコードがあります..非常に単純で、少し面倒で(申し訳ありません)、現在壊れています(ただし、フィードバックの試行が削除され、フィードフォワードの試行に置き換えられれば機能します)。
class Program
{
private static AndGate _andGate;
private static XorGate _xorGate;
static void Main(string[] args)
{
var data = new List<decimal>();
var data2 = new List<decimal>();
var output = new List<Tuple<Bit, Bit, Bit>>();
var rnd = new Random();
//for (var i = 0; i < 10000; i++)
//{
// data.Add(rnd.Next(0, 100));
// data2.Add(rnd.Next(0, 100));
//}
data.Add(10);
data.Add(30);
data.Add(80);
data.Add(5);
data.Add(34);
data.Add(27);
data2.Add(10);
data2.Add(5);
data2.Add(10);
data2.Add(34);
data2.Add(67);
data2.Add(80);
var stream = data.ToObservable();
var stream2 = data2.ToObservable();
var filter = new DataFilter(stream, a => a > 27);
var filter2 = new DataFilter(stream2, a => a < 12);
_andGate = new AndGate {InputA = filter.OutputStream};
_andGate.InputB = new XorGate(filter2.OutputStream, _andGate.Output.Publish()).Output;
_andGate.SetOutput();
//filter.OutputStream.Subscribe(x => Console.WriteLine(x));
//filter2.OutputStream.Subscribe(x => Console.WriteLine(x));
_andGate.Output.Subscribe(x=>Console.WriteLine(x));
//var zippedSequence =
// Observable.When(
// filter.OutputStream.And(filter2.OutputStream)
// .Then((first, second) => new [] { first, second }));
//zippedSequence.Subscribe(x=>Console.WriteLine("{0}, {1}", x[0], x[1]));
Console.ReadLine();
}
}
public class DataFilter
{
protected IObservable<Bit> ValueStream;
public IObservable<Bit> OutputStream
{
get { return ValueStream; }
}
public DataFilter(IObservable<decimal> stream, Func<decimal, bool> operation )
{
ValueStream = stream.Select(a => operation(a)? Bit.High : Bit.Low);
}
}
public class AndGate
{
protected IObservable<Bit> StreamA;
protected IObservable<Bit> StreamB;
protected IObservable<Bit> OutputStream;
public IObservable<Bit> InputA { get { return StreamA; } set { StreamA = value; } }
public IObservable<Bit> InputB { get { return StreamB; } set { StreamB = value; } }
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public AndGate()
{
OutputStream = Observable.When(StreamA.And(StreamB).Then(Determine));
}
public AndGate(IObservable<Bit> streamA, IObservable<Bit> streamB)
{
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High && bitB == Bit.High ? Bit.High : Bit.Low;
}
}
public class OrGate
{
protected IObservable<Bit> InputStreamA;
protected IObservable<Bit> InputStreamB;
protected IObservable<Bit> OutputStream;
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public OrGate()
{
}
public OrGate(IObservable<Bit> streamA, IObservable<Bit> streamB)
{
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High || bitB == Bit.High ? Bit.High : Bit.Low;
}
}
public class XorGate
{
protected IObservable<Bit> StreamA;
protected IObservable<Bit> StreamB;
protected IObservable<Bit> OutputStream;
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public XorGate(IObservable<Bit> streamA, IObservable<Bit> streamB)
{
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High ^ bitB == Bit.High ? Bit.High : Bit.Low;
}
}
public enum Bit { Low = 0, High = 1}
編集:理解を助けるためにこの図を追加しました。赤い線が問題の原因です。;-)
別の編集:私はこの小さな問題を解決し続け、Rx の Generate 要素と Publish/Connect 要素を発見しました。これにより、この問題を解決できました。ゲートネットワークの出力を公開することにより、出力を調べ、出力値に基づいてネットワークの要素の変更を設定することが可能になります。Generate メソッドを使用すると、1 つの High と 1 つの Low (最初) の 2 つの内部ビット ストリームを持つ xor ゲートをセットアップできます。出力はこの配置から High になります。xor ゲートには、発行された出力ストリームを使用してゲートの外部から設定できるステータス ビットがあります。このメソッドは、xor ゲートの出力を High または Low にラッチします。
class Program
{
private static AndGate _andGate1;
private static AndGate _andGate2;
private static XorGate _xorGate;
static void Main(string[] args)
{
var data = new List<decimal>();
var data2 = new List<decimal>();
var output = new List<Tuple<Bit, Bit, Bit>>();
var rnd = new Random();
//for (var i = 0; i < 10000; i++)
//{
// data.Add(rnd.Next(0, 100));
// data2.Add(rnd.Next(0, 100));
//}
data.Add(10);
data.Add(23);
data.Add(80);
data.Add(5);
data.Add(34);
data.Add(27);
data2.Add(10);
data2.Add(5);
data2.Add(10);
data2.Add(34);
data2.Add(67);
data2.Add(80);
//Raw Data streams
var stream = data.ToObservable();
var stream2 = data2.ToObservable();
//Converted to Bit streams
var filter = new DataFilter(stream, a => a > 27);
var filter2 = new DataFilter(stream2, a => a < 12);
//Gate network
_xorGate = new XorGate();
_andGate1 = new AndGate(filter.OutputStream, _xorGate.Output);
_andGate2 = new AndGate(_andGate1.Output, filter2.OutputStream );
//Publish and Connect to the outcome of the network
var observable = _andGate2.Output.SubscribeOn(NewThreadScheduler.Default).Publish();
observable.Connect();
//Subscribe to the outcome to allow changes to be made to the XorGate
observable.Subscribe(x => { if (x == Bit.High) { _xorGate.SetStatusBitHigh(x); } });
//View the results
observable.Subscribe(x => Console.WriteLine(x));
Console.ReadLine();
}
}
public class DataFilter
{
protected IObservable<Bit> ValueStream;
public IObservable<Bit> OutputStream
{
get { return ValueStream; }
}
public DataFilter(IObservable<decimal> stream, Func<decimal, bool> operation )
{
ValueStream = stream.Select(a => operation(a)? Bit.High : Bit.Low);
}
}
public class AndGate
{
protected IObservable<Bit> OutputStream;
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public AndGate(IObservable<Bit> streamA, IObservable<Bit> streamB)
{
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High && bitB == Bit.High ? Bit.High : Bit.Low;
}
}
/// <summary>
/// This is really a bastardized XorGate as I force two Bit streams into the inputs
/// Keep one High, start the other Low and then send it High when a high signal results from the output of the network
/// This allows me to force the network output low i.e. take no action...
/// ...until the Bit is sent low again by another network (no done yet)
/// </summary>
public class XorGate
{
protected IObservable<Bit> StreamA;
protected IObservable<Bit> StreamB;
protected IObservable<Bit> OutputStream;
protected Bit StatusBit;
public void SetStatusBitHigh(Bit input)
{
//No action if circumstances are as you want them
if (input == StatusBit) return;
//Belt and Braces check here
if (StatusBit == Bit.Low && input == Bit.High)
{
StatusBit = Bit.High;
}
}
public void SetStatusBitLow(Bit input)
{
//No action if circumstances are as you want them
if (input == StatusBit) return;
//Belt and Braces check here
if (StatusBit == Bit.High && input == Bit.Low)
{
StatusBit = Bit.Low;
}
}
/// <summary>
/// Output the stream safely
/// </summary>
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public XorGate()
{
//Set the StatusBit to Low initially
StatusBit = Bit.Low;
//Create a permanent high stream for one of the (imaginary) gate pins
var streamA = Observable.Generate(Bit.High, bit => true, bit => bit, bit => bit);
//Create a low stream for the other (imaginary) pin
//One which sets itself to the value of the StatusBit so that a StatusBit = Bit.High will produce a High stream
var streamB = Observable.Generate(Bit.Low, bit => true, bit => StatusBit, bit => bit);
//Produce the output
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High ^ bitB == Bit.High ? Bit.High : Bit.Low;
}
}
public class OrGate
{
protected IObservable<Bit> OutputStream;
public IObservable<Bit> Output
{
get { return OutputStream; }
}
public OrGate(IObservable<Bit> streamA, IObservable<Bit> streamB)
{
OutputStream = Observable.When(streamA.And(streamB).Then(Determine));
}
private Bit Determine(Bit bitA, Bit bitB)
{
return bitA == Bit.High || bitB == Bit.High ? Bit.High : Bit.Low;
}
}
public enum Bit { Low = 0, High = 1}
今のサーキットはこんな感じ
コメントの修正と提案を歓迎し、他のより良い方法でこれを達成します.