Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在给定概率下,从状态s1随机进入状态s2_C#_Random_State - Fatal编程技术网

C# 在给定概率下,从状态s1随机进入状态s2

C# 在给定概率下,从状态s1随机进入状态s2,c#,random,state,C#,Random,State,好的,假设我有一个具有“state”属性的类foo。我需要一个随机选择一个新状态的函数,它有以下限制:一些转换是不允许的,每个转换都有不同的发生概率 enum PossibleStates { A, B, C, D } PossibleStates currentState; float[,] probabilities; 概率[s1,s2]说明从状态s1到状态s2的概率。它也可以是0.0f,这意味着s1->s2是不可能的,概率[s1,s2]可以不同于概率[s2,s1]。我需要这个方法尽可能

好的,假设我有一个具有“state”属性的类
foo
。我需要一个随机选择一个新状态的函数,它有以下限制:一些转换是不允许的,每个转换都有不同的发生概率

enum PossibleStates { A, B, C, D }
PossibleStates currentState;

float[,] probabilities;
概率[s1,s2]
说明从状态s1到状态s2的概率。它也可以是0.0f,这意味着s1->s2是不可能的,
概率[s1,s2]
可以不同于
概率[s2,s1]
。我需要这个方法尽可能的通用,这样就可以有三种甚至三百种可能的状态。
这不是家庭作业,我只是需要一个好的起点,因为我不知道从哪里开始:)


欢呼声

对于从状态a的转换,您将计算一个(均匀分布的)介于0和1之间的随机数
r
。你有转移概率:
p1
p2
,…,
pn
,它们的总和显然必须是1。现在,如果
r
,则遵循第一个转换;否则,如果
r
,则执行第二次转换,依此类推

注意:为了生成所需的随机数,您将获得一个(单个)
random
对象,并调用方法:


对于从状态a的转换,计算0到1之间的(均匀分布)随机数
r
。你有转移概率:
p1
p2
,…,
pn
,它们的总和显然必须是1。现在,如果
r
,则遵循第一个转换;否则,如果
r
,则执行第二次转换,依此类推

注意:为了生成所需的随机数,您将获得一个(单个)
random
对象,并调用方法:


假设我们有一个函数,它产生一个介于1和100之间的随机值

让我们调用这个函数

 float GetRandomNumber()
 {    
     ....
 }
现在让我们假设我们要生成三个数字,它们有可能发生在以下两种情况下:

案例1)

概率是相互排斥的,也就是说,如果一个发生了,其他的就不会发生

案例2)

概率是独立的,所以它们以自己的概率发生

让我们看看1的结果:

  var mutuallyExclusiveProbs = new List<float>({30,50,20});
  var number = GetRandomNumber();
  var cumulativeValue =0;
  //
  for (int i=0; i++; i<mutuallyExclusiveProbs.Count())
  {
    cumulativeValue += mutuallyExclusiveProbs(i)
    if (number <=cumulativeValue)
    {
       //case found 
       return i;
    }
  }
var mutuallyExclusiveProbs=新列表({30,50,20});
变量编号=GetRandomNumber();
var累积值=0;
//

对于(inti=0;i++;i好的,假设我们有一个函数,它产生一个介于1和100之间的随机值

让我们调用这个函数

 float GetRandomNumber()
 {    
     ....
 }
现在让我们假设我们要生成三个数字,它们有可能发生在以下两种情况下:

案例1)

概率是相互排斥的,也就是说,如果一个发生了,其他的就不会发生

案例2)

概率是独立的,所以它们以自己的概率发生

让我们看看1的结果:

  var mutuallyExclusiveProbs = new List<float>({30,50,20});
  var number = GetRandomNumber();
  var cumulativeValue =0;
  //
  for (int i=0; i++; i<mutuallyExclusiveProbs.Count())
  {
    cumulativeValue += mutuallyExclusiveProbs(i)
    if (number <=cumulativeValue)
    {
       //case found 
       return i;
    }
  }
var mutuallyExclusiveProbs=新列表({30,50,20});
变量编号=GetRandomNumber();
var累积值=0;
//

对于下面的(int i=0;i++;i全功能示例。F5然后点击ENTER以更改状态。 在
States
类中,您可以定义概率和状态

在我的代码中,我假设路由是互斥的(它们的组合概率永远不会超过1)。如果这不是真的,我已经标记了要更改的代码段

namespace RandomStatesProgram
{
    class State
    {
        public string Name;

        private bool current;
        public bool Current
        {
            get { return current; }
            set
            {
                if (current)
                {
                    if (value) StayingHere();
                    else LeavingState();
                }
                else
                {
                    if (value) EnteringState();
                }

                current = value;
            }
        }

        public void StayingHere() { Console.WriteLine("Staying in state " + this.Name); }
        public void EnteringState() { Console.WriteLine("Entering state " + this.Name); }
        public void LeavingState() { Console.WriteLine("Leaving state " + this.Name); }

        public State()
        {
            this.Name = "New";
            this.Current = false;
        }

        public State(string name)
            : this()
        {
            this.Name = name;
        }
    }

    class TransitionCourse
    {
        public State From { get; set; }
        public State To { get; set; }
        public float Probability { get; set; }

        public TransitionCourse(Dictionary<int, State> allStates, int fromState, int toState, float probability)
        {
            if (probability < 0 || probability > 1)
                throw new ArgumentOutOfRangeException("Invalid probability");

            if (!allStates.Keys.Any(K => K == fromState || K == toState))
                throw new ArgumentException("State not found");

            this.From = allStates[fromState];
            this.To = allStates[toState];
            this.Probability = probability;
        }
    }

    static class States
    {
        private static Dictionary<int, State> PossibleStates;
        public static State Current
        {
            get
            {
                if (PossibleStates.Where(S => S.Value.Current).Count() == 1)
                    return PossibleStates.Single(S => S.Value.Current).Value;
                else
                    return null;
            }
        }

        public static List<TransitionCourse> Transitions;

        static States()
        {
            PossibleStates = new Dictionary<int, State>()
            {
                {1, new State("One")}, 
                {2, new State("Two")}, 
                {3, new State("Three")},
                {4, new State("Four")} 
            };

            // example: 50% chance of switching to either state from every one of the three
            // note: it must be  0 <= 3rd param <= 1 of course (it's a probability)
            Transitions = new List<TransitionCourse>()
            {
                new TransitionCourse(PossibleStates,1,2,1f/3f),
                new TransitionCourse(PossibleStates,1,3,1f/3f),
                new TransitionCourse(PossibleStates,1,4,1f/3f),
                new TransitionCourse(PossibleStates,2,1,1f),            
                new TransitionCourse(PossibleStates,3,1,1f),
                new TransitionCourse(PossibleStates,4,1,1f)               
            };
        }

        public static void GoTo(int targetState)
        {
            if (!PossibleStates.Keys.Contains(targetState))
                throw new ArgumentException("Invalid state");

            foreach (KeyValuePair<int, State> state in PossibleStates.OrderByDescending(S=>S.Value.Current))
            {
                //first is the "true" state (the current one) then the others.
                //this way we go OUT from a state before going IN another one.
                state.Value.Current = state.Key.Equals(targetState);
            }
        }

        public static void Travel()
        {
            if (Current == null)
                throw new InvalidOperationException("Current state not set");

            TransitionCourse[] exits = Transitions.Where(T => T.From.Equals(Current)).OrderBy(T=>T.Probability).ToArray();
            if (exits.Length == 0) //nowhere to go from here
                return;
            else
                if (exits.Length == 1) //not much to choose here
                {
                    GoTo(PossibleStates.Single(S => S.Value.Equals(exits.First().To)).Key);
                }
                else //ok now we have a choice
                {
                    //we need a "random" number
                    double p = new Random().NextDouble();

                    // remapping probabilities so we can choose "randomly"
                    // this works IF the sum of all transitions probability does not exceed 1.
                    // if it does, at best this'll act weird
                    for (int i = 1; i < exits.Length; i++)
                    {
                        exits[i].Probability += exits[i - 1].Probability;
                        if (exits[i].Probability > p)
                        {
                            GoTo(PossibleStates.Single(S => S.Value.Equals(exits[i].To)).Key);
                            return;
                        }
                    }
                }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            States.GoTo(1);
            while (Console.ReadLine().ToUpper() != "Q")
            {
                States.Travel();
            }
        }
    }
}
命名空间随机状态程序
{
阶级国家
{
公共字符串名称;
私有布尔电流;
公共波电流
{
获取{返回当前;}
设置
{
如果(当前)
{
if(value)StayingHere();
else LeavingState();
}
其他的
{
如果(值)输入状态();
}
电流=值;
}
}
public void StayingHere(){Console.WriteLine(“保持状态”+this.Name);}
public void EnteringState(){Console.WriteLine(“进入状态”+this.Name);}
public void LeavingState(){Console.WriteLine(“离开状态”+this.Name);}
公共国家()
{
this.Name=“New”;
这个。当前=错误;
}
公共状态(字符串名称)
:此()
{
this.Name=Name;
}
}
类传递过程
{
来自{get;set;}的公共状态
公共状态{get;set;}
公共浮点概率{get;set;}
公共TransitionCourse(字典所有状态、int-fromState、int-toState、浮点概率)
{
如果(概率<0 | |概率>1)
抛出新ArgumentOutOfRangeException(“无效概率”);
if(!allStates.Keys.Any(K=>K==fromState | | K==toState))
抛出新ArgumentException(“未找到状态”);
this.From=allStates[fromState];
this.To=allStates[toState];
这个。概率=概率;
}
}
静态类状态
{
私有静态字典可能属性;
公共静态电流
{
得到
{
if(PossibleStates.Where(S=>S.Value.Current).Count()==1)
返回PossibleStates.Single(S=>S.Value.Current).Value;
其他的
返回null;
}
}
公共静态列表转换;
静态()
{
可能属性=新字典()
{
{1,新国家(“一”)},
{2,新国家(“两个”)},
{3,新州(“三”)},
{4,新州(“四”)}
};
//示例:从三种状态中的每一种切换到任一状态的几率为50%
//注意:它必须是0(p)
{