template <int partition=0> inline ftype pullCapacity(int dim) const { assert_leq(alpha[dim], -edges[dim]); assert_geq(alpha[dim], edges[dim]); // Actually the amount that can be pushed to the other node, so in // the 1-partition it's return -edges[dim] + ( (partition == 1) ? 1 : -1) * alpha[dim]; }
/** * Sanity-check various pieces of the Ebwt */ void Ebwt::sanityCheckAll(int reverse) const { const EbwtParams& eh = this->_eh; assert(isInMemory()); // Check ftab for(uint32_t i = 1; i < eh._ftabLen; i++) { assert_geq(this->ftabHi(i), this->ftabLo(i-1)); assert_geq(this->ftabLo(i), this->ftabHi(i-1)); assert_leq(this->ftabHi(i), eh._bwtLen+1); } assert_eq(this->ftabHi(eh._ftabLen-1), eh._bwtLen); // Check offs int seenLen = (eh._bwtLen + 31) >> 5; uint32_t *seen; try { seen = new uint32_t[seenLen]; // bitvector marking seen offsets } catch(bad_alloc& e) { cerr << "Out of memory allocating seen[] at " << __FILE__ << ":" << __LINE__ << endl; throw e; } memset(seen, 0, 4 * seenLen); uint32_t offsLen = eh._offsLen; for(uint32_t i = 0; i < offsLen; i++) { assert_lt(this->offs()[i], eh._bwtLen); int w = this->offs()[i] >> 5; int r = this->offs()[i] & 31; assert_eq(0, (seen[w] >> r) & 1); // shouldn't have been seen before seen[w] |= (1 << r); } delete[] seen; // Check nPat assert_gt(this->_nPat, 0); // Check plen, flen for(uint32_t i = 0; i < this->_nPat; i++) { assert_geq(this->plen()[i], 0); } // Check rstarts if(this->rstarts() != NULL) { for(uint32_t i = 0; i < this->_nFrag-1; i++) { assert_gt(this->rstarts()[(i+1)*3], this->rstarts()[i*3]); if(reverse == REF_READ_REVERSE) { assert(this->rstarts()[(i*3)+1] >= this->rstarts()[((i+1)*3)+1]); } else { assert(this->rstarts()[(i*3)+1] <= this->rstarts()[((i+1)*3)+1]); } } } // Check ebwt sanityCheckUpToSide(eh._numSides); VMSG_NL("Ebwt::sanityCheck passed"); }
inline void pushExcess(const node_ptr& src, const node_ptr& dest, const DirDim& dd, ftype amount) { int direction = dd.direction(); int dim = dd.dimension(); #ifndef NDEBUG assert(direction == -1 || direction == 1); assert(dest == lattice.neighbor(src, dim, direction)); assert_equal(src->on(), partition); assert_equal(dest->on(), partition); assert_geq(dim, 0); assert_leq(amount, pushCapacity<partition>(src, dest, dd)); assert_leq(-amount, pushCapacity<partition>(dest, src, dd.reversed())); assert(direction == 1 || direction == -1); _debugVerifyNodeReduction(src); _debugVerifyNodeReduction(dest); ftype src_pr_excess = src->template excess<partition>(); ftype dest_pr_excess = dest->template excess<partition>(); #endif src->reduction -= ((partition == 1) ? 1 : -1) * amount; dest->reduction += ((partition == 1) ? 1 : -1) * amount; ((direction > 0) ? src : dest) ->alpha[dim] += direction * ((partition == 1) ? 1 : -1) * amount; #ifndef NDEBUG _debugVerifyNodeReduction(src); _debugVerifyNodeReduction(dest); ftype src_af_excess = src->template excess<partition>(); ftype dest_af_excess = dest->template excess<partition>(); assert_equal(src_pr_excess - amount, src_af_excess); assert_equal(dest_pr_excess + amount, dest_af_excess); #endif }
void Scheduler::_handleButtonPress( int updateElId, ButtonType type, int floor ) { // first setup lights Command lights{ type == ButtonType::CallUp ? CommandType::TurnOnLightUp : CommandType::TurnOnLightDown, Command::ANY_ID, floor }; _forwardToTargets( lights ); // each elevator schedules changes originating from it if ( updateElId == _localElevId ) { // now find optimal elevator int minDistance = INT_MAX; int minId = INT_MIN; for ( auto &statepair : _globalState.elevators() ) { const ElevatorState &state = statepair.second; int dist = std::abs( state.lastFloor - floor ); // penalizations for non-idle elevators if ( state.stopped ) dist += 10 * (_bounds.maxFloor() - _bounds.minFloor()); // stopped penalization if ( ( state.direction == Direction::Up && ( (type == ButtonType::CallUp && floor > state.lastFloor ) || floor == _bounds.maxFloor() ) ) || ( state.direction == Direction::Down && ( (type == ButtonType::CallDown && floor < state.lastFloor ) || floor == _bounds.minFloor() ) ) ) dist += _bounds.maxFloor() - _bounds.minFloor() + 1; // busy penalization else if ( state.direction != Direction::None ) // not idle // as a last resort we can schedule floor even to elevator which is // running in different direction dist += 2 * (_bounds.maxFloor() - _bounds.minFloor() + 1); // penalization if ( dist < minDistance ) { minDistance = dist; minId = state.id; } } assert_leq( 0, minId, "no minimal distance found" ); Command comm{ type == ButtonType::CallUp ? CommandType::CallToFloorAndGoUp : CommandType::CallToFloorAndGoDown, minId, floor }; _forwardToTargets( comm ); } }
/** * Check that the ebwt array is internally consistent up to (and not * including) the given side index by re-counting the chars and * comparing against the embedded occ[] arrays. */ void Ebwt::sanityCheckUpToSide(int upToSide) const { assert(isInMemory()); uint32_t occ[] = {0, 0, 0, 0}; ASSERT_ONLY(uint32_t occ_save[] = {0, 0, 0, 0}); uint32_t cur = 0; // byte pointer const EbwtParams& eh = this->_eh; bool fw = false; while(cur < (upToSide * eh._sideSz)) { assert_leq(cur + eh._sideSz, eh._ebwtTotLen); for(uint32_t i = 0; i < eh._sideBwtSz; i++) { uint8_t by = this->ebwt()[cur + (fw ? i : eh._sideBwtSz-i-1)]; for(int j = 0; j < 4; j++) { // Unpack from lowest to highest bit pair int twoBit = unpack_2b_from_8b(by, fw ? j : 3-j); occ[twoBit]++; } assert_eq(0, (occ[0] + occ[1] + occ[2] + occ[3]) % 4); } assert_eq(0, (occ[0] + occ[1] + occ[2] + occ[3]) % eh._sideBwtLen); // Finished forward bucket; check saved [A], [C], [G] and [T] // against the uint32_ts encoded here ASSERT_ONLY(const uint32_t *u32ebwt = reinterpret_cast<const uint32_t*>(&ebwt()[cur + eh._sideBwtSz])); ASSERT_ONLY(uint32_t as = u32ebwt[0]); ASSERT_ONLY(uint32_t cs = u32ebwt[1]); ASSERT_ONLY(uint32_t gs = u32ebwt[2]); ASSERT_ONLY(uint32_t ts = u32ebwt[3]); assert(as == occ_save[0] || as == occ_save[0]-1); assert_eq(cs, occ_save[1]); assert_eq(gs, occ_save[2]); assert_eq(ts, occ_save[3]); #ifndef NDEBUG occ_save[0] = occ[0]; occ_save[1] = occ[1]; occ_save[2] = occ[2]; occ_save[3] = occ[3]; #endif cur += eh._sideSz; } }
static void driver(const string& infile, vector<string>& infiles, const string& outfile, bool reverse = false) { vector<FileBuf*> is; bool bisulfite = false; RefReadInParams refparams(color, reverse ? reverseType : REF_READ_FORWARD, nsToAs, bisulfite); assert_gt(infiles.size(), 0); if(format == CMDLINE) { // Adapt sequence strings to stringstreams open for input stringstream *ss = new stringstream(); for(size_t i = 0; i < infiles.size(); i++) { (*ss) << ">" << i << endl << infiles[i] << endl; } FileBuf *fb = new FileBuf(ss); assert(fb != NULL); assert(!fb->eof()); assert(fb->get() == '>'); ASSERT_ONLY(fb->reset()); assert(!fb->eof()); is.push_back(fb); } else { // Adapt sequence files to ifstreams for(size_t i = 0; i < infiles.size(); i++) { FILE *f = fopen(infiles[i].c_str(), "rb"); if (f == NULL) { cerr << "Error: could not open "<< infiles[i] << endl; throw 1; } FileBuf *fb = new FileBuf(f); assert(fb != NULL); assert(!fb->eof()); assert(fb->get() == '>'); ASSERT_ONLY(fb->reset()); assert(!fb->eof()); is.push_back(fb); } } // Vector for the ordered list of "records" comprising the input // sequences. A record represents a stretch of unambiguous // characters in one of the input sequences. vector<RefRecord> szs; vector<uint32_t> plens; std::pair<size_t, size_t> sztot; { if(verbose) cout << "Reading reference sizes" << endl; Timer _t(cout, " Time reading reference sizes: ", verbose); if(!reverse && (writeRef || justRef)) { // For forward reference, dump it to .3.ebwt and .4.ebwt // files string file3 = outfile + ".3." + gEbwt_ext; string file4 = outfile + ".4." + gEbwt_ext; // Open output stream for the '.3.ebwt' file which will // hold the size records. ofstream fout3(file3.c_str(), ios::binary); if(!fout3.good()) { cerr << "Could not open index file for writing: \"" << file3 << "\"" << endl << "Please make sure the directory exists and that permissions allow writing by" << endl << "Bowtie." << endl; throw 1; } BitpairOutFileBuf bpout(file4.c_str()); // Read in the sizes of all the unambiguous stretches of // the genome into a vector of RefRecords. The input // streams are reset once it's done. writeU<int32_t>(fout3, 1, bigEndian); // endianness sentinel if(color) { refparams.color = false; // Make sure the .3.ebwt and .4.ebwt files contain // nucleotides; not colors TIndexOff numSeqs = 0; fastaRefReadSizes(is, szs, plens, refparams, &bpout, numSeqs); refparams.color = true; writeU<TIndexOffU>(fout3, (TIndexOffU)szs.size(), bigEndian); // write # records for(size_t i = 0; i < szs.size(); i++) { szs[i].write(fout3, bigEndian); } szs.clear(); plens.clear(); // Now read in the colorspace size records; these are // the ones that were indexed TIndexOff numSeqs2 = 0; sztot = fastaRefReadSizes(is, szs, plens, refparams, NULL, numSeqs2); assert_geq(numSeqs, numSeqs2); } else { TIndexOff numSeqs = 0; sztot = fastaRefReadSizes(is, szs, plens, refparams, &bpout, numSeqs); writeU<TIndexOffU>(fout3, (TIndexOffU)szs.size(), bigEndian); // write # records for(size_t i = 0; i < szs.size(); i++) szs[i].write(fout3, bigEndian); } if(sztot.first == 0) { cerr << "Error: No unambiguous stretches of characters in the input. Aborting..." << endl; throw 1; } assert_gt(sztot.first, 0); assert_gt(sztot.second, 0); bpout.close(); fout3.close(); #ifndef NDEBUG if(sanityCheck) { BitPairReference bpr( outfile, // ebwt basename color, // expect color? true, // sanity check? &infiles,// files to check against NULL, // sequences to check against format == CMDLINE, // whether infiles contains strings true, // load sequence? false, // use memory-mapped files false, // use shared memory false, // sweep through memory-mapped memory false, // be talkative false); // be talkative } #endif } else { // Read in the sizes of all the unambiguous stretches of the // genome into a vector of RefRecords TIndexOff numSeqs = 0; sztot = fastaRefReadSizes(is, szs, plens, refparams, NULL, numSeqs); #ifndef NDEBUG if(refparams.color) { refparams.color = false; vector<RefRecord> szs2; vector<uint32_t> plens2; TIndexOff numSeqs2 = 0; fastaRefReadSizes(is, szs2, plens2, refparams, NULL, numSeqs2); assert_leq(numSeqs, numSeqs2); // One less color than base refparams.color = true; } #endif } } if(justRef) return; assert_gt(sztot.first, 0); assert_gt(sztot.second, 0); assert_gt(szs.size(), 0); // Construct Ebwt from input strings and parameters Ebwt<TStr> ebwt(refparams.color ? 1 : 0, lineRate, linesPerSide, offRate, // suffix-array sampling rate -1, // ISA sampling rate ftabChars, // number of chars in initial arrow-pair calc nthreads, outfile, // basename for .?.ebwt files !reverse, // fw !entireSA, // useBlockwise bmax, // block size for blockwise SA builder bmaxMultSqrt, // block size as multiplier of sqrt(len) bmaxDivN, // block size as divisor of len noDc? 0 : dcv,// difference-cover period is, // list of input streams szs, // list of reference sizes plens, // list of not-all-gap reference sequence lengths (TIndexOffU)sztot.first, // total size of all unambiguous ref chars refparams, // reference read-in parameters seed, // pseudo-random number generator seed -1, // override offRate -1, // override isaRate verbose, // be talkative autoMem, // pass exceptions up to the toplevel so that we can adjust memory settings automatically sanityCheck); // verify results and internal consistency // Note that the Ebwt is *not* resident in memory at this time. To // load it into memory, call ebwt.loadIntoMemory() if(verbose) { // Print Ebwt's vital stats ebwt.eh().print(cout); } if(sanityCheck) { // Try restoring the original string (if there were // multiple texts, what we'll get back is the joined, // padded string, not a list) ebwt.loadIntoMemory( refparams.color ? 1 : 0, -1, false, false); TStr s2; ebwt.restore(s2); ebwt.evictFromMemory(); { TStr joinedss = Ebwt<TStr>::join( is, // list of input streams szs, // list of reference sizes (TIndexOffU)sztot.first, // total size of all unambiguous ref chars refparams, // reference read-in parameters seed); // pseudo-random number generator seed if(refparams.reverse == REF_READ_REVERSE) { reverseInPlace(joinedss); } assert_eq(length(joinedss), length(s2)); assert_eq(joinedss, s2); } if(verbose) { if(length(s2) < 1000) { cout << "Passed restore check: " << s2 << endl; } else { cout << "Passed restore check: (" << length(s2) << " chars)" << endl; } } } }