#include <iostream>
#include <cstdio>
#include <fstream>
#include <map>
#include <stdlib.h>
#include <set>
#include <string>
#include <queue>
#include <algorithm>
#include <math.h>
#include <vector>
#include <cstring>
using namespace std;
class Node
{ public:
int target;
set<int> dataset;
set<int> unused;
set<int> used;
string templ;
};
double h(double a,double b){
double l1,l2;
if (a==0)
l1=0.0;
else
l1=(-a)*log2(a);
if(b==0)
l2=0.0;
else
l2=(-b)*log2(b);
return l1+l2;
}
double cal(int d00,int d01,int d10,int d11){
double total=d00+d01+d10+d11+0.0;
double d0,d1,res;
if ((d00+d01) > 0)
d0=(d00+d01)*h(d00/(d00+d01+0.0),d01/(d00+d01+0.0))/(total);
else
d0=0.0;
if ((d10+d11) > 0)
d1=(d10+d11)*h(d10/(d10+d11+0.0),d11/(d10+d11+0.0))/(total);
else
d1=0.0;
res=d0+d1;
return res;
}
void get_intersection(set<int> a,set<int> b,set <int> &res){
res.clear();
set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(res,res.begin()));
}
void get_union(set<int> a,set<int> b,set <int> &res){
res.clear();
set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(res,res.begin()));
}
int finddigs(string x){
int count=0;
for(int i=0;i<x.length();i++){
if(x[i]=='0'||x[i]=='1')
count++;
}
return count;
}
main(int argc, char *argv[]) {
ifstream signals(argv[1]);
ifstream trace(argv[2]);
ifstream lookup(argv[3]);
int depth=atoi(argv[4]);
ifstream output(argv[5]);
int varcount=atoi(argv[6]);
int genprops=atoi(argv[7]);
int linelength=varcount*depth;
map< int, set<int> > zerotable;
map< int, set<int> > onetable;
vector<string> tracelines;
int lineno=0;
while(1){
if(trace.eof())
break;
char temp[linelength+1];
trace>>temp;
if(strlen(temp)==0)
continue;
int i;
for(i=0;i<linelength;i++){
if(temp[i]=='0')
zerotable[i].insert(lineno);
else if(temp[i]=='1')
onetable[i].insert(lineno);
}
string str(temp);
tracelines.push_back(str);
lineno++;
}
lineno=lineno-1;
map<string,int> signal_dict;
int i=0;
vector<string> sig_list;
while(1){
if(signals.eof())
break;
string signame;
signals>>signame;
if(signame.length()==0)
continue;
signal_dict[signame]=i;
i++;
sig_list.push_back(signame);
}
set<int> lookup_vars;
while(1){
if(lookup.eof())
break;
string l;
lookup>>l;
if(l.length()==0)
continue;
int x=signal_dict[l];
for(i=x+varcount;i<linelength;i=i+varcount){
lookup_vars.insert(i);
}
}
queue<Node> nqueue;
while(1){
if(output.eof())
break;
string l;
output>>l;
if(l.length()==0)
continue;
Node node;
node.target=signal_dict[l];
for(int i=0;i<lineno;i++){
node.dataset.insert(i);
}
node.unused=lookup_vars;
node.templ.assign(linelength,'.');
nqueue.push(node);
}
vector<Node> leaf_nodes;
while((nqueue.size()>0) && (leaf_nodes.size() < genprops)) {
Node cur_node=nqueue.front();
nqueue.pop();
double gain=0.0;
int best=-1;
int m00=0;
int m01=0;
int m10=0;
int m11=0;
set<int> mdata00;
set<int> mdata01;
set<int> mdata10;
set<int> mdata11;
set<int> matched00;
set<int> matched01;
set<int> matched10;
set<int> matched11;
set<int> pos;
set<int> neg;
get_intersection(cur_node.dataset,zerotable[cur_node.target],pos);
get_intersection(cur_node.dataset,onetable[cur_node.target],neg);
if(pos.size()==0 && neg.size()==0)
continue;
if((pos.size()==0 || neg.size()==0) && (pos.size()!=0 || neg.size()!=0)) {
if(pos.size()==0){
cur_node.templ[cur_node.target]='1';
}
else
cur_node.templ[cur_node.target]='0';
if(cur_node.used.size()>0)
leaf_nodes.push_back(cur_node);
continue;
}
if(cur_node.unused.size()==0)
continue;
double ent=h((pos.size()/(pos.size()+neg.size()+0.0)),(neg.size()/(pos.size()+neg.size()+0.0)));
for(set<int>::iterator it=cur_node.unused.begin();it!=cur_node.unused.end();it++){
set<int> temp;
get_intersection(zerotable[*it],zerotable[cur_node.target],temp);
get_intersection(temp,cur_node.dataset,matched00);
get_intersection(zerotable[*it],onetable[cur_node.target],temp);
get_intersection(temp,cur_node.dataset,matched01);
get_intersection(onetable[*it],zerotable[cur_node.target],temp);
get_intersection(temp,cur_node.dataset,matched10);
get_intersection(onetable[*it],onetable[cur_node.target],temp);
get_intersection(temp,cur_node.dataset,matched11);
if((matched00.size()+matched01.size()+matched10.size()+matched11.size())==0)
continue;
double entropy=cal(matched00.size(),matched01.size(),matched10.size(),matched11.size());
if((ent-entropy)>gain){
best=*it;
m00=matched00.size();
m01=matched01.size();
m10=matched10.size();
m11=matched11.size();
mdata00=matched00;
mdata01=matched01;
mdata10=matched10;
mdata11=matched11;
gain=(ent-entropy);
}
}
int p=m00+m10;
int n=m01+m11;
if (best != -1){
if((m00+m01)>0){
Node node0;
get_union(mdata01,mdata00,node0.dataset);
node0.target=cur_node.target;
node0.templ=cur_node.templ;
node0.templ[best]='0';
node0.unused=cur_node.unused;
node0.unused.erase(best);
node0.used=cur_node.used;
node0.used.insert(best%varcount);
nqueue.push(node0);
}
if((m10+m11)>0){
Node node1;
get_union(mdata11,mdata10,node1.dataset);
node1.target=cur_node.target;
node1.templ=cur_node.templ;
node1.templ[best]='1';
node1.unused=cur_node.unused;
node1.unused.erase(best);
node1.used=cur_node.used;
node1.used.insert(best%varcount);
nqueue.push(node1);
}
}
}
ofstream propsfile("properties.txt");
ofstream conffile("belief.txt");
ofstream tempfile("template.txt");
for(int it=0;it<leaf_nodes.size();it++){
Node cur_node=leaf_nodes[it];
int usedlen=cur_node.used.size();
if(usedlen<1)
continue;
tempfile<<cur_node.templ<<endl;
string assertion("");
int level=0;
int cur_level=depth-1;
bool printed=false;
bool first=true;
assertion+="((";
bool started=false;
set<string> unique;
for(set<int>::iterator ds=cur_node.dataset.begin();ds!=cur_node.dataset.end();ds++){
string line("");
for(int ind=varcount;ind<linelength;ind+=varcount){
//set<int> used=sort(cur_node.used);
for(set<int>::iterator usd=cur_node.used.begin();usd!=cur_node.used.end();usd++){
line+=tracelines[*ds][*usd+ind];
}
}
unique.insert(line);
}
int totalprops=(depth-1)*(cur_node.used.size()+1);
int usedprops=finddigs(cur_node.templ);
double conf=(unique.size()+0.0)/pow(2,(totalprops - usedprops ));
conffile<<conf<<endl;
for(int i=linelength-1;i>varcount;i--){
if( i/varcount != cur_level){
cur_level-=1;
level+=1;
printed=false;
first=true;
}
if (cur_node.templ[i]!='.'){
if(!printed&& cur_level!=depth-1 && started){
assertion+="##"+string(1,(char)(level+48))+" " ;
level=0;
printed=true;
first=true;
}
if(first){
assertion+=string(sig_list[i%varcount])+"=="+string(1,cur_node.templ[i])+" ";
first=false;
started=true;
}
else{
assertion+="&& "+string(sig_list[i%varcount])+"=="+string(1,cur_node.templ[i])+" ";
started=true;
}
}
}
assertion+=") |=> ("+string(sig_list[cur_node.target])+"=="+string(1,cur_node.templ[cur_node.target])+"));";
propsfile<<assertion<<endl;
}
}