File indexing completed on 2026-08-06 09:24:12
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef CVOLVER_ColourFlowBasis_hpp_included
0009 #define CVOLVER_ColourFlowBasis_hpp_included
0010
0011 #include <vector>
0012 #include <map>
0013 #include <set>
0014 #include <cassert>
0015 #include <algorithm>
0016
0017 namespace CVolver {
0018
0019
0020
0021
0022 template<class ForwardIterator, class T>
0023 void iota(ForwardIterator begin, ForwardIterator end, T value) {
0024 while ( begin != end ) {
0025 *begin = value;
0026 value += 1;
0027 ++begin;
0028 }
0029 }
0030
0031
0032
0033
0034 inline std::vector<std::size_t> identicalPermutation(const std::size_t n) {
0035 std::vector<std::size_t> res(n);
0036 CVolver::iota(res.begin(),res.end(),0);
0037 return res;
0038 }
0039
0040
0041
0042
0043 template<class Rnd>
0044 std::vector<std::size_t> randomPermutation(const std::size_t n, Rnd& rnd) {
0045 std::vector<std::size_t> pick = identicalPermutation(n);
0046 std::vector<std::size_t> res(n);
0047 std::size_t count = 0;
0048 while ( !pick.empty() ) {
0049 std::size_t i = rnd.template uniform_int_distribution<std::size_t>(0,pick.size()-1);
0050 res[count] = pick[i];
0051 pick.erase(pick.begin()+i);
0052 ++count;
0053 }
0054 return res;
0055 }
0056
0057
0058
0059
0060 class ColourFlow {
0061
0062 public:
0063
0064
0065
0066
0067 ColourFlow() {}
0068
0069
0070
0071
0072 explicit ColourFlow(const std::vector<size_t>& perm)
0073 : thePermutation(perm) {}
0074
0075
0076
0077
0078 template<class Rnd>
0079 static ColourFlow randomFlow(const std::size_t& n, Rnd& rnd) {
0080 return ColourFlow(randomPermutation(n,rnd));
0081 }
0082
0083
0084
0085
0086 static std::set<ColourFlow> allFlows(const std::size_t& n);
0087
0088
0089
0090
0091 bool operator==(const ColourFlow& other) const {
0092 return thePermutation == other.thePermutation;
0093 }
0094
0095
0096
0097
0098 bool operator!=(const ColourFlow& other) const {
0099 return thePermutation != other.thePermutation;
0100 }
0101
0102
0103
0104
0105 bool operator<(const ColourFlow& other) const {
0106 return thePermutation < other.thePermutation;
0107 }
0108
0109
0110
0111
0112 ColourFlow& conjugate() {
0113 std::vector<std::size_t> tmp = thePermutation;
0114 for ( std::size_t k = 0; k < tmp.size(); ++k ) {
0115 thePermutation[tmp[k]] = k;
0116 }
0117 return *this;
0118 }
0119
0120
0121
0122
0123
0124 std::size_t scalarProduct(const ColourFlow& other) const;
0125
0126
0127
0128
0129 const std::vector<std::size_t>& permutation() const {
0130 return thePermutation;
0131 }
0132
0133
0134
0135
0136 const std::size_t& antiColour(const std::size_t& i) const {
0137 assert(i < thePermutation.size());
0138 return thePermutation[i];
0139 }
0140
0141
0142
0143
0144 std::size_t colour(const std::size_t& i) const {
0145 std::vector<std::size_t>::const_iterator k =
0146 std::find(thePermutation.begin(),thePermutation.end(),i);
0147 assert(k != thePermutation.end());
0148 return std::distance(thePermutation.begin(),k);
0149 }
0150
0151
0152
0153
0154
0155 std::pair<std::size_t,std::size_t> getTranspositionOf(const ColourFlow& other) const;
0156
0157
0158
0159
0160 ColourFlow& swap(const std::size_t& i, const std::size_t& j) {
0161 assert(i < thePermutation.size() && j < thePermutation.size());
0162 std::swap(thePermutation[i],thePermutation[j]);
0163 return *this;
0164 }
0165
0166
0167
0168
0169
0170 ColourFlow& emitSinglet() {
0171 thePermutation.push_back(thePermutation.size());
0172 return *this;
0173 }
0174
0175
0176
0177
0178 ColourFlow& emitFromColour(const std::size_t& i) {
0179 assert(i < thePermutation.size());
0180 thePermutation.push_back(thePermutation[i]);
0181 thePermutation[i] = thePermutation.size()-1;
0182 return *this;
0183 }
0184
0185
0186
0187
0188 ColourFlow& emitFromAntiColour(const std::size_t& i) {
0189 return emitFromColour(colour(i));
0190 }
0191
0192
0193
0194
0195
0196 bool isNonZero(const std::vector<std::size_t>& colours,
0197 const std::vector<std::size_t>& antiColours) const;
0198
0199
0200
0201
0202 size_t nLegs() const { return thePermutation.size(); }
0203
0204 private:
0205
0206
0207
0208
0209
0210 std::vector<std::size_t> thePermutation;
0211
0212 };
0213
0214
0215
0216
0217 template<class ParticleData>
0218 struct ParticleDataTraits {
0219
0220
0221
0222
0223 static bool isSinglet(const ParticleData&) { return true; }
0224
0225
0226
0227
0228 static bool isAntiFundamental(const ParticleData&) { return false; }
0229
0230
0231
0232
0233 static bool isFundamental(const ParticleData&) { return false; }
0234
0235
0236
0237
0238 static bool isAdjoint(const ParticleData&) { return false; }
0239
0240 };
0241
0242
0243
0244
0245 class ColourFlowCrossing {
0246
0247 private:
0248
0249
0250
0251
0252 void addColourCrossing(const std::size_t& leg,
0253 std::size_t& count,
0254 double sign) {
0255 theColourMap[count] = leg;
0256 theColourCrossingSigns[count] = sign;
0257 theReverseColourMap[leg] = count;
0258 ++count;
0259 }
0260
0261
0262
0263
0264 void addAntiColourCrossing(const std::size_t& leg,
0265 std::size_t& count,
0266 double sign) {
0267 theAntiColourMap[count] = leg;
0268 theAntiColourCrossingSigns[count] = sign;
0269 theReverseAntiColourMap[leg] = count;
0270 ++count;
0271 }
0272
0273 public:
0274
0275
0276
0277
0278 ColourFlowCrossing()
0279 : theNFlows(0) {}
0280
0281
0282
0283
0284 template<class ParticleData>
0285 explicit ColourFlowCrossing(const std::vector<ParticleData>& proc,
0286 bool signs = true)
0287 : theNFlows(0) {
0288 typedef ParticleDataTraits<ParticleData> Traits;
0289 std::size_t colourCounter = 0;
0290 std::size_t antiColourCounter = 0;
0291 for ( std::size_t k = 0; k < proc.size(); ++k ) {
0292 if ( Traits::isSinglet(proc[k]) )
0293 continue;
0294 double sign = k > 1 ? 1. : -1.;
0295 if ( Traits::isAntiFundamental(proc[k]) ) {
0296 if ( k > 1 )
0297 addAntiColourCrossing(k,antiColourCounter,signs ? sign : 1.0);
0298 else
0299 addColourCrossing(k,colourCounter,signs ? sign : 1.0);
0300 }
0301 if ( Traits::isFundamental(proc[k]) ) {
0302 if ( k > 1 )
0303 addColourCrossing(k,colourCounter,signs ? sign : 1.0);
0304 else
0305 addAntiColourCrossing(k,antiColourCounter,signs ? sign : 1.0);
0306 }
0307 if ( Traits::isAdjoint(proc[k]) ) {
0308 addColourCrossing(k,colourCounter,1.0);
0309 addAntiColourCrossing(k,antiColourCounter,1.0);
0310 }
0311 }
0312 theNFlows = colourCounter;
0313 }
0314
0315
0316
0317
0318 const std::size_t& nFlows() const { return theNFlows; }
0319
0320
0321
0322
0323 std::size_t colourLeg(const std::size_t& i) const {
0324 std::map<std::size_t,std::size_t>::const_iterator l =
0325 theColourMap.find(i);
0326 assert(l != theColourMap.end());
0327 return l->second;
0328 }
0329
0330
0331
0332
0333 std::size_t antiColourLeg(const std::size_t& i) const {
0334 std::map<std::size_t,std::size_t>::const_iterator l =
0335 theAntiColourMap.find(i);
0336 assert(l != theAntiColourMap.end());
0337 return l->second;
0338 }
0339
0340
0341
0342
0343 std::size_t colourCrossingSign(const std::size_t& i) const {
0344 std::map<std::size_t,double>::const_iterator l =
0345 theColourCrossingSigns.find(i);
0346 assert(l != theColourCrossingSigns.end());
0347 return l->second;
0348 }
0349
0350
0351
0352
0353 double antiColourCrossingSign(const std::size_t& i) const {
0354 std::map<std::size_t,double>::const_iterator l =
0355 theAntiColourCrossingSigns.find(i);
0356 assert(l != theAntiColourCrossingSigns.end());
0357 return l->second;
0358 }
0359
0360
0361
0362
0363 bool coloured(const std::size_t& i) const {
0364 return theReverseColourMap.find(i) != theReverseColourMap.end();
0365 }
0366
0367
0368
0369
0370 std::size_t colourLine(const std::size_t& i) const {
0371 std::map<std::size_t,std::size_t>::const_iterator l =
0372 theReverseColourMap.find(i);
0373 assert(l != theReverseColourMap.end());
0374 return l->second;
0375 }
0376
0377
0378
0379
0380 bool antiColoured(const std::size_t& i) const {
0381 return theReverseAntiColourMap.find(i) != theReverseAntiColourMap.end();
0382 }
0383
0384
0385
0386
0387 std::size_t antiColourLine(const std::size_t& i) const {
0388 std::map<std::size_t,std::size_t>::const_iterator l =
0389 theReverseAntiColourMap.find(i);
0390 assert(l != theReverseAntiColourMap.end());
0391 return l->second;
0392 }
0393
0394 private:
0395
0396
0397
0398
0399 std::size_t theNFlows;
0400
0401
0402
0403
0404 std::map<std::size_t,std::size_t> theColourMap;
0405
0406
0407
0408
0409 std::map<std::size_t,std::size_t> theAntiColourMap;
0410
0411
0412
0413
0414 std::map<std::size_t,std::size_t> theReverseColourMap;
0415
0416
0417
0418
0419 std::map<std::size_t,std::size_t> theReverseAntiColourMap;
0420
0421
0422
0423
0424 std::map<std::size_t,double> theColourCrossingSigns;
0425
0426
0427
0428
0429 std::map<std::size_t,double> theAntiColourCrossingSigns;
0430
0431 };
0432
0433 }
0434
0435 #endif