removed timestamp from event id

This commit is contained in:
Luong Hoang 2016-06-03 10:54:39 -04:00
Родитель d591682f76
Коммит 64cfb9bd25
10 изменённых файлов: 80 добавлений и 88 удалений

Просмотреть файл

@ -33,6 +33,7 @@
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<DocumentationFile>..\bin\AnyCPU\Release\Microsoft.Research.MultiWorldTesting.ExploreLibrary.XML</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="BaseExplorer.cs" /> <Compile Include="BaseExplorer.cs" />
@ -55,12 +56,15 @@
<Compile Include="MultiActionHelper.cs" /> <Compile Include="MultiActionHelper.cs" />
<Compile Include="TopSlotExplorer.cs" /> <Compile Include="TopSlotExplorer.cs" />
<Compile Include="UniformRandomExploration.cs" /> <Compile Include="UniformRandomExploration.cs" />
<Compile Include="UniqueEventID.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="GitLink, Version=2.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\gitlink.2.2.0\lib\net45\GitLink.exe</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<HintPath>..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> <Private>True</Private>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
</ItemGroup> </ItemGroup>

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
/// <param name="uniqueKey">A user-defined identifer for the decision.</param> /// <param name="uniqueKey">A user-defined identifer for the decision.</param>
/// <param name="modelId">Optional; The Id of the model used to make predictions/decisions, if any exists at decision time.</param> /// <param name="modelId">Optional; The Id of the model used to make predictions/decisions, if any exists at decision time.</param>
/// <param name="isExplore">Optional; Indicates whether the decision was generated purely from exploration (vs. exploitation).</param> /// <param name="isExplore">Optional; Indicates whether the decision was generated purely from exploration (vs. exploitation).</param>
void Record(TContext context, TAction value, object explorerState, object mapperState, UniqueEventID uniqueKey); void Record(TContext context, TAction value, object explorerState, object mapperState, string uniqueKey);
} }
public interface IExplorer<TAction, TPolicyValue> public interface IExplorer<TAction, TPolicyValue>

Просмотреть файл

@ -111,6 +111,13 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
} }
} }
public TAction ChooseAction(string uniqueKey, TContext context, IContextMapper<TContext, TPolicyValue> defaultPolicy)
{
var policy = this.Policy;
var policyDecision = (policy ?? defaultPolicy).MapContext(context);
return ChooseActionInternal(uniqueKey, context, policyDecision);
}
/// <summary> /// <summary>
/// Choose an action (or decision to take) given the exploration algorithm and context. /// Choose an action (or decision to take) given the exploration algorithm and context.
/// </summary> /// </summary>
@ -119,46 +126,35 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
/// <param name="context">The context upon which a decision is made. See SimpleContext above for an example.</param> /// <param name="context">The context upon which a decision is made. See SimpleContext above for an example.</param>
/// <param name="numActionsVariable">Optional; Number of actions available which may be variable across decisions.</param> /// <param name="numActionsVariable">Optional; Number of actions available which may be variable across decisions.</param>
/// <returns>An unsigned 32-bit integer representing the 1-based chosen action.</returns> /// <returns>An unsigned 32-bit integer representing the 1-based chosen action.</returns>
public TAction ChooseAction(UniqueEventID uniqueKey, TContext context, TAction initialAction) public TAction ChooseAction(string uniqueKey, TContext context, TPolicyValue defaultPolicyDecision)
{ {
// Note: thread-safe atomic reference access // Note: thread-safe atomic reference access
var policy = this.Policy; var policy = this.Policy;
if (policy == null) var policyDecision = (policy != null) ? policy.MapContext(context) : defaultPolicyDecision;
{ return ChooseActionInternal(uniqueKey, context, policyDecision);
// policy not ready & initial action provided
this.Log(uniqueKey,
context,
ExplorerDecision.Create(initialAction, new GenericExplorerState { Probability = 1 }, true));
return initialAction;
}
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey.Key) + this.appId;
PRG random = new PRG(saltedSeed);
var policyDecision = policy.MapContext(context);
var explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, this.numActionsProvider.GetNumberOfActions(context));
this.Log(uniqueKey, context, explorerDecision, policyDecision);
return explorerDecision.Value;
} }
public TAction ChooseAction(UniqueEventID uniqueKey, TContext context) public TAction ChooseAction(string uniqueKey, TContext context)
{ {
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey.Key) + this.appId; ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey) + this.appId;
PRG random = new PRG(saltedSeed); PRG random = new PRG(saltedSeed);
var policy = this.Policy; var policy = this.Policy;
ExplorerDecision<TAction> explorerDecision; ExplorerDecision<TAction> explorerDecision;
PolicyDecision<TPolicyValue> policyDecision = null; PolicyDecision<TPolicyValue> policyDecision = null;
int numActionsVariable = this.numActionsProvider.GetNumberOfActions(context);
if (numActionsVariable <= 0)
{
throw new Exception("Could not determine number of actions from the provided context.");
}
if (policy == null) if (policy == null)
explorerDecision = this.InitialExplorer.Explore(random, this.numActionsProvider.GetNumberOfActions(context)); explorerDecision = this.InitialExplorer.Explore(random, numActionsVariable);
else else
{ {
policyDecision = policy.MapContext(context); policyDecision = policy.MapContext(context);
explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, this.numActionsProvider.GetNumberOfActions(context)); explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, numActionsVariable);
} }
this.Log(uniqueKey, context, explorerDecision, policyDecision != null ? policyDecision.MapperState : null); this.Log(uniqueKey, context, explorerDecision, policyDecision != null ? policyDecision.MapperState : null);
@ -166,14 +162,6 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
return explorerDecision.Value; return explorerDecision.Value;
} }
private void Log(UniqueEventID uniqueKey, TContext context, ExplorerDecision<TAction> explorerDecision, object policyState = null)
{
if (explorerDecision.ShouldRecord)
{
this.recorder.Record(context, explorerDecision.Value, explorerDecision.ExplorerState, policyState, uniqueKey);
}
}
/// <summary> /// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary> /// </summary>
@ -183,6 +171,32 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
private TAction ChooseActionInternal(string uniqueKey, TContext context, PolicyDecision<TPolicyValue> policyDecision)
{
ulong saltedSeed = MurMurHash3.ComputeIdHash(uniqueKey) + this.appId;
PRG random = new PRG(saltedSeed);
int numActionsVariable = this.numActionsProvider.GetNumberOfActions(context);
if (numActionsVariable <= 0)
{
throw new Exception("Could not determine number of actions from the provided context.");
}
var explorerDecision = this.Explorer.MapContext(random, policyDecision.Value, numActionsVariable);
this.Log(uniqueKey, context, explorerDecision, policyDecision);
return explorerDecision.Value;
}
private void Log(string uniqueKey, TContext context, ExplorerDecision<TAction> explorerDecision, object policyState = null)
{
if (explorerDecision.ShouldRecord)
{
this.recorder.Record(context, explorerDecision.Value, explorerDecision.ExplorerState, policyState, uniqueKey);
}
}
private void Dispose(bool disposing) private void Dispose(bool disposing)
{ {
if (disposing) if (disposing)

Просмотреть файл

@ -26,5 +26,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.3")] [assembly: AssemblyVersion("1.0.0.4")]
[assembly: AssemblyFileVersion("1.0.0.3")] [assembly: AssemblyFileVersion("1.0.0.4")]

Просмотреть файл

@ -25,11 +25,11 @@ namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary.SingleAction
/// <param name="action">Chosen by an exploration algorithm given context.</param> /// <param name="action">Chosen by an exploration algorithm given context.</param>
/// <param name="probability">The probability of the chosen action given context.</param> /// <param name="probability">The probability of the chosen action given context.</param>
/// <param name="uniqueKey">A user-defined identifer for the decision.</param> /// <param name="uniqueKey">A user-defined identifer for the decision.</param>
public void Record(TContext context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey) public void Record(TContext context, int value, object explorerState, object mapperState, string uniqueKey)
{ {
recordingBuilder.Append(value.ToString(CultureInfo.InvariantCulture)); recordingBuilder.Append(value.ToString(CultureInfo.InvariantCulture));
recordingBuilder.Append(' '); recordingBuilder.Append(' ');
recordingBuilder.Append(uniqueKey.Key); recordingBuilder.Append(uniqueKey);
recordingBuilder.Append(' '); recordingBuilder.Append(' ');
recordingBuilder.Append(((GenericExplorerState)explorerState).Probability.ToString("0.00000", CultureInfo.InvariantCulture)); recordingBuilder.Append(((GenericExplorerState)explorerState).Probability.ToString("0.00000", CultureInfo.InvariantCulture));

Просмотреть файл

@ -1,27 +0,0 @@
using System;
namespace Microsoft.Research.MultiWorldTesting.ExploreLibrary
{
/// <summary>
/// Represents a unique identifier for an event.
/// </summary>
public class UniqueEventID
{
/// <summary>
/// The key for the event.
/// </summary>
/// <remarks>
/// This key is used as a seed to the randomization, which
/// ensures consistent experience within same event, but
/// random across events.
/// </remarks>
public string Key { get; set; }
/// <summary>
/// The time stamp of the event which, together with the key,
/// uniquely identify an event. Events with same key
/// must have the same time stamp.
/// </summary>
public DateTime TimeStamp { get; set; }
}
}

Просмотреть файл

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="net45" /> <package id="gitlink" version="2.2.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
</packages> </packages>

Просмотреть файл

@ -20,7 +20,7 @@ namespace cs_test
/// </summary> /// </summary>
class MyRecorder : IRecorder<MyContext, int> class MyRecorder : IRecorder<MyContext, int>
{ {
public void Record(MyContext context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey) public void Record(MyContext context, int value, object explorerState, object mapperState, string uniqueKey)
{ {
// Stores the tuple internally in a vector that could be used later for other purposes. // Stores the tuple internally in a vector that could be used later for other purposes.
interactions.Add(new Interaction<MyContext>() interactions.Add(new Interaction<MyContext>()
@ -28,7 +28,7 @@ namespace cs_test
Context = context, Context = context,
Action = (uint)value, Action = (uint)value,
Probability = ((GenericExplorerState)explorerState).Probability, Probability = ((GenericExplorerState)explorerState).Probability,
UniqueKey = uniqueKey.Key UniqueKey = uniqueKey
}); });
} }
@ -134,7 +134,7 @@ namespace cs_test
// Performs exploration by passing an instance of the Epsilon-Greedy exploration algorithm into MwtExplorer // Performs exploration by passing an instance of the Epsilon-Greedy exploration algorithm into MwtExplorer
// using a sample string to uniquely identify this event // using a sample string to uniquely identify this event
string uniqueKey = "eventid"; string uniqueKey = "eventid";
int action = mwtt.ChooseAction(new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow }, context); int action = mwtt.ChooseAction(uniqueKey, context);
Console.WriteLine(recorder.GetRecording()); Console.WriteLine(recorder.GetRecording());
@ -151,7 +151,7 @@ namespace cs_test
//MwtExplorer<MyContext> mwtt = new MwtExplorer<MyContext>("mwt", recorder); //MwtExplorer<MyContext> mwtt = new MwtExplorer<MyContext>("mwt", recorder);
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, new TauFirstExplorer(tau), new MyPolicy()); var mwtt = MwtExplorer.Create("mwt", numActions, recorder, new TauFirstExplorer(tau), new MyPolicy());
int action = mwtt.ChooseAction(new UniqueEventID { Key = "key", TimeStamp = DateTime.UtcNow }, new MyContext()); int action = mwtt.ChooseAction("key", new MyContext());
Console.WriteLine(String.Join(",", recorder.GetAllInteractions().Select(it => it.Action))); Console.WriteLine(String.Join(",", recorder.GetAllInteractions().Select(it => it.Action)));
return; return;
} }

Просмотреть файл

@ -315,7 +315,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());
@ -358,7 +358,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue; int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());
@ -401,7 +401,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue; int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());
@ -422,7 +422,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue; int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());
@ -464,7 +464,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue; int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());
@ -486,7 +486,7 @@ namespace BlackBoxTests
for (int i = 0; i < experimentalUnitIdList.Length; i++) for (int i = 0; i < experimentalUnitIdList.Length; i++)
{ {
int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue; int numActionsVariable = isVariableActionContext ? ((IVariableActionContext)contextList[i]).GetNumberOfActions() : int.MaxValue;
mwt.ChooseAction(new UniqueEventID { Key = experimentalUnitIdList[i] }, contextList[i]); mwt.ChooseAction(experimentalUnitIdList[i], contextList[i]);
} }
File.AppendAllText(outputFile, recorder.GetRecording()); File.AppendAllText(outputFile, recorder.GetRecording());

Просмотреть файл

@ -44,7 +44,7 @@ namespace ExploreTests.SingleAction
where TContext : RegularTestContext where TContext : RegularTestContext
{ {
string uniqueKey = "ManagedTestId"; string uniqueKey = "ManagedTestId";
var uniqueId = new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow }; var uniqueId = uniqueKey;
TestRecorder<TContext> recorder = new TestRecorder<TContext>(); TestRecorder<TContext> recorder = new TestRecorder<TContext>();
//MwtExplorer<TContext> mwtt = new MwtExplorer<TContext>("mwt", recorder); //MwtExplorer<TContext> mwtt = new MwtExplorer<TContext>("mwt", recorder);
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, policy); var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, policy);
@ -98,7 +98,7 @@ namespace ExploreTests.SingleAction
where TContext : RegularTestContext where TContext : RegularTestContext
{ {
string uniqueKey = "ManagedTestId"; string uniqueKey = "ManagedTestId";
var uniqueId = new UniqueEventID { Key = uniqueKey, TimeStamp = DateTime.UtcNow }; var uniqueId = uniqueKey;
var recorder = new TestRecorder<TContext>(); var recorder = new TestRecorder<TContext>();
@ -240,7 +240,7 @@ namespace ExploreTests.SingleAction
Random rand = new Random(); Random rand = new Random();
for (uint i = 0; i < contexts.Length; i++) for (uint i = 0; i < contexts.Length; i++)
{ {
var uniqueId = new UniqueEventID { Key = rand.NextDouble().ToString(), TimeStamp = DateTime.UtcNow }; var uniqueId = rand.NextDouble().ToString();
int chosenAction = mwtt.ChooseAction(uniqueId, contexts[i]); int chosenAction = mwtt.ChooseAction(uniqueId, contexts[i]);
actions[chosenAction - 1]++; // action id is one-based actions[chosenAction - 1]++; // action id is one-based
} }
@ -273,9 +273,9 @@ namespace ExploreTests.SingleAction
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer); var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer);
Random rand = new Random(); Random rand = new Random();
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 100 }); mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 100 });
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 101 }); mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 101 });
mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = 102 }); mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = 102 });
var interactions = recorder.GetAllInteractions(); var interactions = recorder.GetAllInteractions();
@ -305,7 +305,7 @@ namespace ExploreTests.SingleAction
explorer.EnableExplore(false); explorer.EnableExplore(false);
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
{ {
int chosenAction = mwtt.ChooseAction(new UniqueEventID { Key = rand.NextDouble().ToString() }, new RegularTestContext() { Id = (int)i }); int chosenAction = mwtt.ChooseAction(rand.NextDouble().ToString(), new RegularTestContext() { Id = (int)i });
Assert.AreEqual(highestScoreAction, chosenAction); Assert.AreEqual(highestScoreAction, chosenAction);
} }
} }
@ -339,7 +339,7 @@ namespace ExploreTests.SingleAction
//var mwtt = new MwtExplorer<TContext>("mwt", recorder); //var mwtt = new MwtExplorer<TContext>("mwt", recorder);
var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer); var mwtt = MwtExplorer.Create("mwt", numActions, recorder, explorer, scorer);
int chosenAction = mwtt.ChooseAction(new UniqueEventID { Key = uniqueKey }, testContext); int chosenAction = mwtt.ChooseAction(uniqueKey, testContext);
var interactions = recorder.GetAllInteractions(); var interactions = recorder.GetAllInteractions();
Assert.AreEqual(1, interactions.Count); Assert.AreEqual(1, interactions.Count);
@ -367,14 +367,14 @@ namespace ExploreTests.SingleAction
class TestRecorder<Ctx> : IRecorder<Ctx, int> class TestRecorder<Ctx> : IRecorder<Ctx, int>
{ {
public void Record(Ctx context, int value, object explorerState, object mapperState, UniqueEventID uniqueKey) public void Record(Ctx context, int value, object explorerState, object mapperState, string uniqueKey)
{ {
interactions.Add(new TestInteraction<Ctx>() interactions.Add(new TestInteraction<Ctx>()
{ {
Context = context, Context = context,
Action = (uint)value, Action = (uint)value,
Probability = ((GenericExplorerState)explorerState).Probability, Probability = ((GenericExplorerState)explorerState).Probability,
UniqueKey = uniqueKey.Key UniqueKey = uniqueKey
}); });
} }