C# 在给定概率下,从状态s1随机进入状态s2
好的,假设我有一个具有“state”属性的类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]。我需要这个方法尽可能
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)
{