99 lines
5.4 KiB
C++
99 lines
5.4 KiB
C++
// Isolated feasibility experiment; not wired into production search entry points.
|
|
// Build: g++ -O3 -std=c++17 -march=native research/upper_interval_probe.cpp -o /tmp/upper_interval_probe
|
|
// Tests/benchmark: /tmp/upper_interval_probe
|
|
// mode=0: existing sorted-event solver; mode=1: two running residue intervals.
|
|
#include "slime_solver_core.hpp"
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <random>
|
|
#include <vector>
|
|
#include <stdexcept>
|
|
namespace sr=slime_research;
|
|
using Clock=std::chrono::steady_clock;
|
|
using Cells=std::array<sr::CellTerm,25>;
|
|
struct Emit { std::vector<uint64_t>& v; void operator()(uint64_t s){v.push_back(s);} };
|
|
Cells cells(int x,int z){Cells c;for(int j=0;j<5;j++)for(int i=0;i<5;i++)c[j*5+i]={sr::coordinateTerm(x+i,z+j),sr::kSlime};return c;}
|
|
std::vector<uint32_t> roots(const Cells& c){std::vector<uint32_t> r;for(uint32_t p=0;p<(1u<<18);p++)if(sr::partialPatternPossible(p,18,c.data(),25))r.push_back(p);return r;}
|
|
uint64_t visits=0;
|
|
void fast(uint64_t low,const Cells& c,Emit& emit){
|
|
uint32_t q=sr::nextStateFromTerm(low,c[0].term)>>17;
|
|
++visits;
|
|
if(q&1)return;
|
|
uint32_t b=q>>18,r=q&((1u<<18)-1),t=8192-b;
|
|
uint32_t residue[2]={(r%5+5-b%5)%5,0};residue[1]=(residue[0]+2)%5;
|
|
uint32_t lo[2]={0,t},hi[2]={t,8192};
|
|
unsigned mask=0;
|
|
for(int k=0;k<2;k++)if(sr::firstWithResidue(lo[k],residue[k])<hi[k])mask|=1u<<k;
|
|
for(int i=1;i<25&&mask;i++){
|
|
q=sr::nextStateFromTerm(low,c[i].term)>>17;++visits;
|
|
if(q&1)return;
|
|
b=q>>18;r=q&((1u<<18)-1);t=8192-b;
|
|
uint32_t before=(r%5+5-b%5)%5,after=(before+2)%5;
|
|
for(int k=0;k<2;k++)if(mask&(1u<<k)){
|
|
if(residue[k]==before)hi[k]=std::min(hi[k],t);
|
|
else if(residue[k]==after)lo[k]=std::max(lo[k],t);
|
|
else{mask&=~(1u<<k);continue;}
|
|
if(sr::firstWithResidue(lo[k],residue[k])>=hi[k])mask&=~(1u<<k);
|
|
}
|
|
}
|
|
for(int k=0;k<2;k++)if(mask&(1u<<k))for(uint32_t t0=sr::firstWithResidue(lo[k],residue[k]);t0<hi[k];t0+=5){
|
|
uint64_t s=low+((uint64_t((4965u*t0)&8191))<<35);
|
|
if(sr::verifyPattern(s,c.data(),25))emit(s);
|
|
}
|
|
}
|
|
int main(){
|
|
auto c=cells(51069,419124);auto rr=roots(c);
|
|
std::vector<uint64_t> baseline;
|
|
for(int round=0;round<3;round++)for(int mode=0;mode<2;mode++){
|
|
std::vector<uint64_t> result;Emit e{result};visits=0;auto start=Clock::now();
|
|
for(auto p:rr)for(uint64_t m=0;m<(1u<<17);m++){
|
|
uint64_t s=p+(m<<18);
|
|
if(mode)fast(s,c,e);else sr::solveUpper13(s,c.data(),25,e);
|
|
}
|
|
double sec=std::chrono::duration<double>(Clock::now()-start).count();
|
|
std::sort(result.begin(),result.end());
|
|
if(!mode)baseline=result;else if(result!=baseline)throw std::runtime_error("full search mismatch");
|
|
std::cout<<"round="<<round<<" mode="<<mode<<" seconds="<<sec<<" results="<<result.size()<<" avg_cells="<<double(visits)/(rr.size()*(1u<<17))<<std::endl;
|
|
}
|
|
std::mt19937_64 rng(20261011);
|
|
for(int p=0;p<20;p++){
|
|
auto cc=cells(int(rng()%3750000)-1875000,int(rng()%3750000)-1875000);
|
|
auto rt=roots(cc);
|
|
for(int k=0;k<2000;k++){
|
|
uint64_t s=rt.empty()?(rng()&((1ull<<35)-1)):(rt[rng()%rt.size()]+((rng()%131072)<<18));
|
|
std::vector<uint64_t> a,b;Emit ea{a},eb{b};sr::solveUpper13(s,cc.data(),25,ea);fast(s,cc,eb);
|
|
std::sort(a.begin(),a.end());std::sort(b.begin(),b.end());if(a!=b)throw std::runtime_error("random differential mismatch");
|
|
}
|
|
}
|
|
std::cout<<"differential_cases=40000 passed"<<std::endl;
|
|
// Directly enumerate upper bits as an independent reference, including known-hit planes.
|
|
for(int k=0;k<128;k++){
|
|
uint64_t s=k<int(baseline.size())?(baseline[k]&((1ull<<35)-1)):(rr[rng()%rr.size()]+((rng()%131072)<<18));
|
|
std::vector<uint64_t>a,b;Emit eb{b};fast(s,c,eb);
|
|
for(uint64_t h=0;h<8192;h++){
|
|
uint64_t seed=s+(h<<35);bool ok=true;
|
|
for(auto cell:c)if((sr::nextStateFromTerm(seed,cell.term)>>17)%10){ok=false;break;}
|
|
if(ok&&sr::verifyPattern(seed,c.data(),25))a.push_back(seed);
|
|
}
|
|
std::sort(b.begin(),b.end());if(a!=b)throw std::runtime_error("direct enumeration mismatch");
|
|
}
|
|
std::cout<<"direct_upper_cases=128 passed"<<std::endl;
|
|
auto start=Clock::now();std::vector<unsigned> counts;uint64_t sum=0;unsigned zero=0;
|
|
for(int i=0;i<4096;i++){
|
|
auto cc=cells(int(rng()%3750000)-1875000,int(rng()%3750000)-1875000);
|
|
unsigned n=roots(cc).size();counts.push_back(n);sum+=n;zero+=n==0;
|
|
}
|
|
std::sort(counts.begin(),counts.end());
|
|
std::cout<<"uniform_positions=4096 zero="<<zero<<" roots_mean="<<double(sum)/4096<<" roots_median="<<counts[2048]<<" roots_p95="<<counts[3891]<<" roots_max="<<counts.back()<<" seconds="<<std::chrono::duration<double>(Clock::now()-start).count()<<std::endl;
|
|
start=Clock::now();std::vector<uint64_t> tail;
|
|
const uint64_t inverse=0xDFE05BCB1365ull;
|
|
for(auto cell:c)for(uint64_t v=(uint64_t(2147483640)<<17);v<(1ull<<48);v++){
|
|
uint64_t u=((v-11)*inverse)&sr::kMask48;
|
|
uint64_t seed=((u^sr::kCombinedXor)-cell.term)&sr::kMask48;
|
|
if(sr::verifyPattern(seed,c.data(),25))tail.push_back(seed);
|
|
}
|
|
std::sort(tail.begin(),tail.end());tail.erase(std::unique(tail.begin(),tail.end()),tail.end());
|
|
std::cout<<"rejection_tail_candidates="<<(25ull<<20)<<" exact_unique_matches="<<tail.size()<<" seconds="<<std::chrono::duration<double>(Clock::now()-start).count()<<std::endl;
|
|
}
|