// get neigbouring particles of P and calculate the according connection probabilities void MetropolisHastingsSampler::ComputeEndPointProposalDistribution(EndPoint P) { Particle *p = P.p; int ep = P.ep; float dist,dot; vnl_vector_fixed<float, 3> R = p->GetPos() + (p->GetDir() * (ep*m_ParticleLength) ); m_ParticleGrid->ComputeNeighbors(R); m_SimpSamp.clear(); m_SimpSamp.add(m_StopProb,EndPoint(nullptr,0)); for (;;) { Particle *p2 = m_ParticleGrid->GetNextNeighbor(); if (p2 == nullptr) break; if (p!=p2 && p2->label == 0) { if (p2->mID == -1) { dist = (p2->GetPos() - p2->GetDir() * m_ParticleLength - R).squared_magnitude(); if (dist < m_DistanceThreshold) { dot = dot_product(p2->GetDir(),p->GetDir()) * ep; if (dot > m_CurvatureThreshold) { float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,-1); m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,-1)); } } } if (p2->pID == -1) { dist = (p2->GetPos() + p2->GetDir() * m_ParticleLength - R).squared_magnitude(); if (dist < m_DistanceThreshold) { dot = dot_product(p2->GetDir(),p->GetDir()) * (-ep); if (dot > m_CurvatureThreshold) { float en = m_EnergyComputer->ComputeInternalEnergyConnection(p,ep,p2,+1); m_SimpSamp.add(exp(en/m_TractProb),EndPoint(p2,+1)); } } } } } }
// generate actual proposal (birth, death, shift and connection of particle) void MetropolisHastingsSampler::MakeProposal() { float randnum = m_RandGen->GetVariate(); // Birth Proposal if (randnum < m_BirthProb) { m_BirthTime.Start(); vnl_vector_fixed<float, 3> R; m_EnergyComputer->DrawRandomPosition(R); vnl_vector_fixed<float, 3> N = GetRandomDirection(); Particle prop; prop.GetPos() = R; prop.GetDir() = N; float prob = m_Density * m_DeathProb /((m_BirthProb)*(m_ParticleGrid->m_NumParticles+1)); float ex_energy = m_EnergyComputer->ComputeExternalEnergy(R,N,nullptr); float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop); prob *= exp((in_energy/m_InTemp+ex_energy/m_ExTemp)) ; if (prob > 1 || m_RandGen->GetVariate() < prob) { Particle *p = m_ParticleGrid->NewParticle(R); if (p!=nullptr) { p->GetPos() = R; p->GetDir() = N; m_AcceptedProposals++; } } m_BirthTime.Stop(); } // Death Proposal else if (randnum < m_BirthProb+m_DeathProb) { m_DeathTime.Start(); if (m_ParticleGrid->m_NumParticles > 0) { int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; Particle *dp = m_ParticleGrid->GetParticle(pnum); if (dp->pID == -1 && dp->mID == -1) { float ex_energy = m_EnergyComputer->ComputeExternalEnergy(dp->GetPos(),dp->GetDir(),dp); float in_energy = m_EnergyComputer->ComputeInternalEnergy(dp); float prob = m_ParticleGrid->m_NumParticles * (m_BirthProb) /(m_Density*m_DeathProb); //*SpatProb(dp->R); prob *= exp(-(in_energy/m_InTemp+ex_energy/m_ExTemp)) ; if (prob > 1 || m_RandGen->GetVariate() < prob) { m_ParticleGrid->RemoveParticle(pnum); m_AcceptedProposals++; } } } m_DeathTime.Stop(); } // Shift Proposal else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb) { if (m_ParticleGrid->m_NumParticles > 0) { m_ShiftTime.Start(); int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; Particle *p = m_ParticleGrid->GetParticle(pnum); Particle prop_p = *p; DistortVector(m_Sigma, prop_p.GetPos()); DistortVector(m_Sigma/(2*m_ParticleLength), prop_p.GetDir()); prop_p.GetDir().normalize(); float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.GetPos(),prop_p.GetDir(),p) - m_EnergyComputer->ComputeExternalEnergy(p->GetPos(),p->GetDir(),p); float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p); float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp); if (m_RandGen->GetVariate() < prob) { vnl_vector_fixed<float, 3> Rtmp = p->GetPos(); vnl_vector_fixed<float, 3> Ntmp = p->GetDir(); p->GetPos() = prop_p.GetPos(); p->GetDir() = prop_p.GetDir(); if (!m_ParticleGrid->TryUpdateGrid(pnum)) { p->GetPos() = Rtmp; p->GetDir() = Ntmp; } m_AcceptedProposals++; } m_ShiftTime.Stop(); } } // Optimal Shift Proposal else if (randnum < m_BirthProb+m_DeathProb+m_ShiftProb+m_OptShiftProb) { if (m_ParticleGrid->m_NumParticles > 0) { m_OptShiftTime.Start(); int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; Particle *p = m_ParticleGrid->GetParticle(pnum); bool no_proposal = false; Particle prop_p = *p; if (p->pID != -1 && p->mID != -1) { Particle *plus = m_ParticleGrid->GetParticle(p->pID); int ep_plus = (plus->pID == p->ID)? 1 : -1; Particle *minus = m_ParticleGrid->GetParticle(p->mID); int ep_minus = (minus->pID == p->ID)? 1 : -1; prop_p.GetPos() = (plus->GetPos() + plus->GetDir() * (m_ParticleLength * ep_plus) + minus->GetPos() + minus->GetDir() * (m_ParticleLength * ep_minus)); prop_p.GetPos() *= 0.5; prop_p.GetDir() = plus->GetPos() - minus->GetPos(); prop_p.GetDir().normalize(); } else if (p->pID != -1) { Particle *plus = m_ParticleGrid->GetParticle(p->pID); int ep_plus = (plus->pID == p->ID)? 1 : -1; prop_p.GetPos() = plus->GetPos() + plus->GetDir() * (m_ParticleLength * ep_plus * 2); prop_p.GetDir() = plus->GetDir(); } else if (p->mID != -1) { Particle *minus = m_ParticleGrid->GetParticle(p->mID); int ep_minus = (minus->pID == p->ID)? 1 : -1; prop_p.GetPos() = minus->GetPos() + minus->GetDir() * (m_ParticleLength * ep_minus * 2); prop_p.GetDir() = minus->GetDir(); } else no_proposal = true; if (!no_proposal) { float cos = dot_product(prop_p.GetDir(), p->GetDir()); float p_rev = exp(-((prop_p.GetPos()-p->GetPos()).squared_magnitude() + (1-cos*cos))*m_Gamma)/m_Z; float ex_energy = m_EnergyComputer->ComputeExternalEnergy(prop_p.GetPos(),prop_p.GetDir(),p) - m_EnergyComputer->ComputeExternalEnergy(p->GetPos(),p->GetDir(),p); float in_energy = m_EnergyComputer->ComputeInternalEnergy(&prop_p) - m_EnergyComputer->ComputeInternalEnergy(p); float prob = exp(ex_energy/m_ExTemp+in_energy/m_InTemp)*m_ShiftProb*p_rev/(m_OptShiftProb+m_ShiftProb*p_rev); if (m_RandGen->GetVariate() < prob) { vnl_vector_fixed<float, 3> Rtmp = p->GetPos(); vnl_vector_fixed<float, 3> Ntmp = p->GetDir(); p->GetPos() = prop_p.GetPos(); p->GetDir() = prop_p.GetDir(); if (!m_ParticleGrid->TryUpdateGrid(pnum)) { p->GetPos() = Rtmp; p->GetDir() = Ntmp; } m_AcceptedProposals++; } } m_OptShiftTime.Stop(); } } // Connection Proposal else { if (m_ParticleGrid->m_NumParticles > 0) { m_ConnectionTime.Start(); int pnum = m_RandGen->GetIntegerVariate()%m_ParticleGrid->m_NumParticles; Particle *p = m_ParticleGrid->GetParticle(pnum); EndPoint P; P.p = p; P.ep = (m_RandGen->GetVariate() > 0.5)? 1 : -1; // direction of the new tract RemoveAndSaveTrack(P); // remove old tract and save it for later if (m_BackupTrack.m_Probability != 0) { MakeTrackProposal(P); // propose new tract starting from P float prob = (m_ProposalTrack.m_Energy-m_BackupTrack.m_Energy)/m_InTemp ; prob = exp(prob)*(m_BackupTrack.m_Probability * pow(m_DelProb,m_ProposalTrack.m_Length)) /(m_ProposalTrack.m_Probability * pow(m_DelProb,m_BackupTrack.m_Length)); if (m_RandGen->GetVariate() < prob) { ImplementTrack(m_ProposalTrack); // accept proposed tract m_AcceptedProposals++; } else { ImplementTrack(m_BackupTrack); // reject proposed tract and restore old one } } else ImplementTrack(m_BackupTrack); m_ConnectionTime.Stop(); } } }