C# 使用反应式扩展在逻辑门模拟器中创建稳定的反馈回路?

C# 使用反应式扩展在逻辑门模拟器中创建稳定的反馈回路?,c#,recursion,system.reactive,C#,Recursion,System.reactive,我已经创建了一个非常简单的逻辑门模拟器,它可以在输入端接收IEnumerable feed,并通过一系列门在输出端精确地产生高/低位 其思想是将这一概念扩展到多门网络,将存储在内存数据库中的数组中的值提供给网络的输入,并在逻辑门网络中复制场景评估规则集。假设Rx允许的流式操作应提供及时评估400000个场景的机制,从而避免搜索和阵列迭代。大多数输入仅为前馈输入,但有些输入需要与网络输出一起工作,因为下一个场景的决策依赖于前一个场景的输出 一切正常,直到我尝试在网络中创建一个反馈循环,尝试使用网络

我已经创建了一个非常简单的逻辑门模拟器,它可以在输入端接收IEnumerable feed,并通过一系列门在输出端精确地产生高/低位

其思想是将这一概念扩展到多门网络,将存储在内存数据库中的数组中的值提供给网络的输入,并在逻辑门网络中复制场景评估规则集。假设Rx允许的流式操作应提供及时评估400000个场景的机制,从而避免搜索和阵列迭代。大多数输入仅为前馈输入,但有些输入需要与网络输出一起工作,因为下一个场景的决策依赖于前一个场景的输出

一切正常,直到我尝试在网络中创建一个反馈循环,尝试使用网络的输出流作为一个门的输入流,该门的输出是网络输出分辨率的一部分

我想知道如何获取输出流并以这种方式使用它。我确实看了一下,感觉这可能会有所帮助,但我对Rx非常陌生,并没有完全理解它

这是我到目前为止的代码。非常简单,有点混乱(抱歉)并且当前已被破坏(尽管如果删除反馈尝试并用前馈尝试替换,则会起作用)

类程序
{
专用静态AndGate _AndGate;
私有静态XorGate XorGate;
静态void Main(字符串[]参数)
{
var data=新列表();
var data2=新列表();
var输出=新列表();
var rnd=新随机数();
//对于(变量i=0;i<10000;i++)
//{
//data.Add(rnd.Next(01100));
//data2.Add(rnd.Next(01100));
//}
数据.增加(10);
数据.增加(30);
数据.增加(80);
数据。添加(5);
数据.增加(34);
数据.增加(27);
数据2.添加(10);
数据2.添加(5);
数据2.添加(10);
数据2.Add(34);
数据2.Add(67);
数据2.Add(80);
var stream=data.ToObservable();
var stream2=data2.ToObservable();
变量过滤器=新数据过滤器(流,a=>a>27);
var filter2=新的数据过滤器(stream2,a=>a<12);
_andGate=newandgate{InputA=filter.OutputStream};
_andGate.InputB=新的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));
//变量压缩序列=
//可观察到。什么时候(
//filter.OutputStream.And(filter2.OutputStream)
//。然后((第一,第二)=>new[]{first,second});
//Subscribe(x=>Console.WriteLine(“{0},{1}”,x[0],x[1]);
Console.ReadLine();
}
}
公共类数据过滤器
{
受保护的IObservable ValueStream;
公共IObservable输出流
{
获取{return ValueStream;}
}
公共数据过滤器(IObservable流,Func操作)
{
ValueStream=stream.Select(a=>操作(a)?位高:位低);
}
}
公共类和门
{
受保护的IObservable StreamA;
受保护的可观测流B;
受保护的IObservable输出流;
public IObservable InputA{get{return StreamA;}set{StreamA=value;}}
public IObservable InputB{get{return StreamB;}set{StreamB=value;}}
公共可观测输出
{
获取{return OutputStream;}
}
公共AndGate()
{
OutputStream=可观察的。当(流A和(流B)。然后(确定));
}
公共AndGate(IObservable streamA、IObservable streamB)
{
OutputStream=可观察的。当(流A和(流B)。然后(确定));
}
专用位确定(位A、位B)
{
返回bitA==Bit.High&&bitB==Bit.High?Bit.High:Bit.Low;
}
}
公开课组织
{
受保护的IObservable输入流A;
受保护的IObservable输入流B;
受保护的IObservable输出流;
公共可观测输出
{
获取{return OutputStream;}
}
公共机构
{
}
公共组织(IObservable streamA、IObservable streamB)
{
OutputStream=可观察的。当(流A和(流B)。然后(确定));
}
专用位确定(位A、位B)
{
返回bitA==Bit.High | | bitB==Bit.High?Bit.High:Bit.Low;
}
}
公共类XorGate
{
受保护的IObservable StreamA;
受保护的可观测流B;
受保护的IObservable输出流;
公共可观测输出
{
获取{return OutputStream;}
}
公共XorGate(IObservable streamA、IObservable streamB)
{
OutputStream=可观察的。当(流A和(流B)。然后(确定));
}
普里瓦特
        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}
    public delegate IObservable<T> Feedback<T>(IObservable<T> feedback, out IObservable<T> output);
    public static IObservable<T> FeedbackSystem<T>(Feedback<T> closure)
    {
        IObservable<T> source = Observable.Empty<T>(), output;
        source = closure(Observable.Defer(() => source), out output);
        return output;
    }
        var system =
        FeedbackSystem((IObservable<double> acceleration, out IObservable<double> velocity) =>
        {
            //Time axis: moves forward every 0.1s
            double t = 0.1; var timeaxis = Observable.Interval(TimeSpan.FromSeconds(t));

            velocity = acceleration.Sample(timeaxis)                //move in time
                                   .Scan((u, a) => u + a * t)   //u' = u + at
                                   .Select(u => u + new Random().Next(10))  //some variations in speed
                                   .Publish().RefCount();                   //avoid recalculation

            //negative feedback
            var feedback = velocity.Select(u => 0.5 * (100 - u));

            return feedback.Select(a => Math.Min(a, 15.0))  //new limited acceleration
                           .StartWith(0);                   //initial value          
        });

        system.Subscribe(Console.WriteLine);