public void Dispose() { SourceStates oldValue = (SourceStates)Interlocked.Exchange(ref this.sourceState, (int)SourceStates.Disposed); if (oldValue != SourceStates.Disposed) { if (this.ctRegistration != default(CancellationTokenRegistration)) { this.ctRegistration.Dispose(); this.ctRegistration = default(CancellationTokenRegistration); } if (oldValue == SourceStates.Disposed) // TODO: Check if this is necessary! { Task.Run(() => this.Source.TrySetException(new ObjectDisposedException("Lock awaiter was unexpectedly disposed."))); } } }
public bool TrySignalSource(SourceStates state) { if ((SourceStates)this.sourceState == SourceStates.Disposed) { throw new ObjectDisposedException("SyncTask"); } int oldValue = -1; try { } finally { if ((oldValue = Interlocked.CompareExchange(ref this.sourceState, (int)state, 0)) == 0) { switch (state) { case SourceStates.True: Task.Factory.StartNew(() => { this.Source.TrySetResult(true); }); break; case SourceStates.False: Task.Factory.StartNew(() => { this.Source.TrySetResult(false); }); break; case SourceStates.Canceled: Task.Factory.StartNew(() => { this.Source.TrySetCanceled(); }); if (this.ctRegistration != default(CancellationTokenRegistration)) { this.ctRegistration.Dispose(); this.ctRegistration = default(CancellationTokenRegistration); } break; case SourceStates.Disposed: throw new ArgumentException("SyncTask cannot be disposed this way."); default: break; } } } return(oldValue == 0); }
/// <summary> /// OnNext takes a tuple of an observation and a sequence of /// states that might have emitted this observation (the /// FROM states). The name of the tuple is "value". The /// observation is in "value.Item1" and the sequence of /// states is in "value.Item2". /// </summary> public void OnNext(Tuple <O, IEnumerable <S> > value) { Contract.Requires(value.Item2 != null); // Contract.Requires fails here due to visibility of the properties. Contract.Assert(Iff(TargetStates == null, LastV == null)); // True only first time around -- at bootstrapping time. if (TargetStates == null) { // Initialize the HISTORY LIST of maps from state to // probability-of-most-probable-path. _V = new List <Dictionary <S, double> >(); // Initialize the map from state to // most-probable-path-leading-to-state. Path = new Dictionary <S, List <S> >(); // Initialize the FIRST map from state to probability // of most-probable-path leading to the state. var firstV = new Dictionary <S, double>(); // value.Item2 contains the FROM states: the states // that might have emitted this observation. Now // compute the probabilities for transition to all the // TO states. In this bootstrapping case, the // probabilities are simply the emission // probabilities -- the probabilities that the state // produced this observation -- times the probability // that the system was in that state. foreach (var state in value.Item2) { // The probability of the most probable path // leading to "state" given observation is the // a-priori probability of state times the // conditional probability of observation given // the state. Observation is in the slot // "value.Item1." firstV[state] = StartingProbabilities(state) * EmissionProbabilities(state, value.Item1); // The state that yielded the transition to this // most probable path is just "state" itself. Path[state] = new List <S>(); Path[state].Add(state); } // The possible targets for the next transition are in // the states, in-turn in slot "value.Item2." TargetStates = value.Item2; _V.Add(firstV); LastV = firstV; return; } // The source states for this observation are the target // states from the last observation (Viterbi, strictly // speaking, has a memory of ONE transition). In case of // the first observation -- the bootstrapping case, this // is also true, it just so happens that the source and // target states are the same during bootstrapping. SourceStates = TargetStates; // The target states for this observation are in the input // to OnNext. TargetStates = value.Item2; // Space for the new probabilities of the // most-probable-paths leading to each state. var nextV = new Dictionary <S, double>(); // and for each candidate target state . . . foreach (var target in TargetStates) { // . . . find the SOURCE state that leads to the most // probable path to the target. // // Maximize over the prior states: the transition // probabilities from the source state, times the // conditional probabilities of seeing the actual // observation given the candidate source state, times // the probability of the most-probable-path leading // to the source state. Use the LINQ non-standard // query operator "ArgAndMax," which, for any // IEnumerable, finds the input (the arg or "source") // that produces the maximum value of its given // function (lambda expression), and also that maximum // value, returning both the argument and the maximum // in an instance of class ArgumentValuePair. // // In this lambda expression, "target" is fixed // (closed over). var maxStateAndProb = SourceStates.ArgAndMax(source => { // probability of the most probable path that led // to source var a = LastV[source]; // transition probability from source to target var b = TransitionProbabilities(source, target); // probability of seeing actual observation if we // are in the target state; observation is stored // in value.Item1. var c = EmissionProbabilities(target, value.Item1); return(a * b * c); }); // After this point, we have found the SOURCE state // that produces the most probable path to the given // target state and yielding the given observation. // Save the probability of that most-probable-path. nextV[target] = maxStateAndProb.Value; // Copy the most probable path that led to the source // state that yields the maximum probability. I must // copy it because this path might be the same for // multiple targets, and each target will need its own // copy of the prior path to append itself to. var newpath = new List <S>(Path[maxStateAndProb.Argument]); // Append the current state. newpath.Add(target); // Replace the path to the current target with the // refreshed one. Path[target] = newpath; } _V.Add(nextV); LastV = nextV; }