いま,SAT問題(充足可能性問題)についてC++で作っています.
data.in に含まれるデータを隣接行列に見立ててそこから各ノードが隣接しているか判断しています.
data.in においては行列の上半分だけデータとして取り込んでいます.(下半分は同じ事なんで)
問題になっているのは sat.cpp での二重 for ループにある
// 論理関数に登録する.
booleanfunc.push_back(clause(tlit1, tlit2));
booleanfunc.push_back(clause(flit1, flit2));
が問題になっています.これを実行すると
a, b
0xbfae3e94
a1, b1,
0xbfae3e94
a0, b0,
a, c
0xbfae3e94
a1, c1,
0xbfae3e94
a0, c0,
0xbfae3e94
a1, c1,
0xbfae3e94
a0, c0,
a, e
0xbfae3e94
a1, e1,
0xbfae3e94
a0, e0,
0xbfae3e94
a1, e1,
0xbfae3e94
a0, e0,
0xbfae3e94
a1, e1,
0xbfae3e94
a0, e0,
と表示され期待通りになりません.
私が期待しているのは booleanfunc は
booleanfunc
+--------+--------+--------+--------+--------+
| 0x11 | 0x12 | 0x13 | 0x14 | 0x15 |
+--------+--------+--------+--------+--------+
このようにばらばらのアドレスを保存させたいのです.
(アドレスが一緒だったら引数を変えても同じものとりますもんね^^;)
関数 clause 内では新しく new で領域をとっているつもりなのですが同じ領域をとってしまいます.
どうにかならないでしょうか?
あと,ヘッダファイルで int a; とグローバル変数を定義すると
/tmp/cccIwGSL.o:(.bss+0x0): multiple definition of `a'
/tmp/cciZxMSI.o:(.bss+0x0): first defined here
collect2: ld はステータス 1 で終了しました
と怒られます.どのように回避出来ますか?
環境:Linux(Ubuntu8.10) 端末
===data.in===
1101
001
10
0
(上にグラフを描いてみました)
==sat.cpp== メインルーチンを含むプログラム
#include"sat.h"
#include<fstream>
int main(void) {
int NOTREV = 1;
std::ifstream fin;
std::list<std::list<Literal*>*> booleanfunc;
std::list<std::list<Literal*>*>::iterator ipp;
int nodes;
std::cout << "How many nodes in the Graph? >>";
std::cin >> nodes;
fin.open(fname);
if (!fin.is_open()) {
// エラー処理.
exit(1);
}
char c;
char charac1, charac2;
charac1 = 'a'; charac2 = 'b';
for(int i = 0; i < nodes - 1; i++) {
for(int j = 0; j < nodes - NOTREV; j++) {
fin.get(c);
if(CONECT == c) {
// リテラルの生成.
std::cout << charac1 << ", " << charac2 << std::endl;
Literal tlit1(charac1, true), tlit2(charac2, true);
Literal flit1(charac1, false), flit2(charac2, false);
// 論理関数に登録する.
booleanfunc.push_back(clause(tlit1, tlit2));
booleanfunc.push_back(clause(flit1, flit2));
for(ipp = booleanfunc.begin(); ipp != booleanfunc.end(); ipp++) {
std::cout << *ipp << std::endl;
}
}
charac2++;
}
// 改行を読み飛ばす.
fin.get(c);
charac1++;
charac2 = 'b' + NOTREV;
NOTREV++;
break;
}
for(ipp = booleanfunc.begin(); ipp != booleanfunc.end(); ipp++) {
//std::cout << *ipp << std::endl;
}
fin.close();
return 0;
}
==sat.h== クラスの定義をするヘッダ
#include<iostream>
#include<stdlib.h>
#include<list>
#include<string>
const char CONECT = '1';
const char fname[/url] = "data.in";
class Expression {
// コピーコンストラクタ・代入演算子の使用を禁止.
private:
Expression(const Expression&);
Expression& operator=(const Expression&);
protected:
char char_;
public:
Expression() : char_(' '){}
Expression(char c) : char_(c) {}
char charac() {return char_;}
};
class Literal : public Expression {
// var_:あり(false),なし(true).
private:
bool var_;
public:
Literal() : Expression(), var_(true) {};
Literal(char lt, bool var) : Expression(lt), var_(var) {};
bool var() {return var_;}
};
std::list<Literal*>* clause(Literal&, Literal&); // clause 関数:節を作成する.
std::ostream& operator<<(std::ostream&, std::list<Literal*>*);
==func.cpp== 具体的な関数の定義をするプログラム
#include"sat.h"
#include<iostream>
std::list<Literal*>* clause(Literal& lit1, Literal& lit2) {
std::list<Literal*>* clause;
clause = new std::list<Literal*>;
clause->push_back(&lit1);
clause->push_back(&lit2);
return clause;
}
std::ostream& operator<<(std::ostream& stream, std::list<Literal*>* lit) {
std::list<Literal*>::iterator it;
std::cout << &lit << std::endl;
for(it = lit->begin(); it != lit->end(); it++) {
stream << (*it)->charac() << (*it)->var();
stream << ", ";
}
return stream;
}