├── Dockerfile ├── LICENSE ├── README.md ├── add_metadata.py ├── docker_build.sh ├── docker_run.sh ├── dqn.py ├── evaluate.py ├── evaluate.sh ├── gqsat ├── __init__.py ├── agents.py ├── buffer.py ├── learners.py ├── models.py └── utils.py ├── minisat ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── __init__.py └── minisat │ ├── __init__.py │ ├── core │ ├── Dimacs.h │ ├── Main.cc │ ├── Solver.cc │ ├── Solver.h │ └── SolverTypes.h │ ├── gym │ ├── GymSolver.cc │ ├── GymSolver.h │ ├── GymSolver.i │ ├── GymSolver.py │ ├── GymSolver_wrap.cxx │ ├── GymSolver_wrap.o │ ├── MiniSATEnv.py │ └── _GymSolver.so │ ├── mtl │ ├── Alg.h │ ├── Alloc.h │ ├── Heap.h │ ├── IntMap.h │ ├── IntTypes.h │ ├── Map.h │ ├── Queue.h │ ├── Rnd.h │ ├── Sort.h │ ├── Vec.h │ └── XAlloc.h │ ├── simp │ ├── Main.cc │ ├── SimpSolver.cc │ └── SimpSolver.h │ └── utils │ ├── Options.cc │ ├── Options.h │ ├── ParseUtils.h │ ├── System.cc │ └── System.h └── train.sh /Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04 16 | 17 | ENV CUDA_PATH /usr/local/cuda 18 | ENV CUDA_INCLUDE_PATH /usr/local/cuda/include 19 | ENV CUDA_LIBRARY_PATH /usr/local/cuda/lib64 20 | 21 | RUN apt-get update -y && apt-get install software-properties-common -y && \ 22 | add-apt-repository -y multiverse && apt-get update -y && apt-get upgrade -y && \ 23 | apt-get install -y apt-utils vim man build-essential wget sudo python3.6 python3-pip htop zlib1g-dev swig&& \ 24 | rm -rf /var/lib/apt/lists/* 25 | 26 | RUN pip3 install --upgrade pip 27 | RUN pip3 install numpy scipy pyyaml matplotlib ruamel.yaml networkx tensorboardX 28 | RUN pip3 install torch==1.1.0 torchvision 29 | RUN pip3 install gym 30 | 31 | ENV CUDA_HOME /usr/local/cuda 32 | ENV CPATH /usr/local/cuda/include 33 | ENV LD_LIBRARY_PATH /usr/local/cuda/lib64:/home/gqsat_user/gqsat/minisat/build/release/lib:$LD_LIBRARY_PATH 34 | ENV TORCH_CUDA_ARCH_LIST="6.0 6.1 7.0+PTX 7.5+PTX" 35 | 36 | RUN pip3 install --verbose --no-cache-dir torch_scatter 37 | RUN pip3 install --verbose --no-cache-dir torch-sparse 38 | RUN pip3 install --verbose --no-cache-dir torch-cluster 39 | RUN pip3 install torch-geometric 40 | 41 | RUN pip3 install tqdm 42 | 43 | RUN useradd -ms /bin/bash gqsat_user 44 | USER gqsat_user 45 | WORKDIR /home/gqsat_user/gqsat 46 | 47 | # to run the minisat binary 48 | ENV PATH /home/gqsat_user/gqsat/minisat/build/release/bin:$PATH 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GQSAT 2 | 3 | Can Q-learning with Graph Networks learn a Generalizable Branching Heuristic for a SAT solver? 4 | 5 | ## How to add metadata for evaluation 6 | 7 | ```python3 add_metadata.py --eval-problems-paths ``` 8 | 9 | ## How to train 10 | 11 | ```./train.sh``` 12 | 13 | ## How to evaluate 14 | 15 | * add the path to the model to the script first 16 | * choose the evaluation dataset 17 | * ```./evaluate.sh``` 18 | 19 | 20 | ## How to build a solver (you need this only if you changed the c++ code) 21 | 22 | Run `make && make python-wrap` in the minisat folder. 23 | 24 | ## How to build swig code (if you changed minisat-python interface, e.g. in GymSolver.i) 25 | 26 | Go to minisat/minisat/gym, run `swig -fastdispatch -c++ -python3 GymSolver.i` and then repeat the building procedure from the previous step. 27 | 28 | ## Individual Contributor License Agreement 29 | 30 | Please fill out the following CLA and email to sgodil@nvidia.com: https://www.apache.org/licenses/icla.pdf 31 | 32 | ## Cite 33 | 34 | ``` 35 | @inproceedings{kurin2019improving, 36 | title={Can Q-Learning with Graph Networks Learn a Generalizable Branching Heuristic for a SAT Solver?}, 37 | author={Kurin, Vitaly and Godil, Saad and Whiteson, Shimon and Catanzaro, Bryan}, 38 | booktitle = {Advances in Neural Information Processing Systems 32}, 39 | year={2020} 40 | } 41 | ``` 42 | 43 | ## Acknowledgements 44 | 45 | We would like to thank [Fei Wang](https://github.com/feiwang3311/minisat) whose initial implementation of the environment we used as a start, and the creators of [Minisat](https://github.com/niklasso/minisat) on which it is based on. 46 | We would also like to thank the creators of [Pytorch Geometric](https://github.com/rusty1s/pytorch_geometric) whose 47 | MetaLayer and [Graph Nets](https://arxiv.org/abs/1806.01261) implementation we built upon. -------------------------------------------------------------------------------- /add_metadata.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import gym, minisat # you need the latter to run __init__.py and register the environment. 17 | from collections import defaultdict 18 | from gqsat.utils import build_argparser 19 | from gqsat.agents import MiniSATAgent 20 | 21 | DEBUG_ROLLOUTS = 10 # if --debug flag is present, run this many of rollouts, not the whole problem folder 22 | 23 | 24 | def main(): 25 | parser = build_argparser() 26 | args = parser.parse_args() 27 | # key is the name of the problem file, value is a list with two values [minisat_steps_no_restarts, minisat_steps_with_restarts] 28 | results = defaultdict(list) 29 | 30 | for with_restarts in [False, True]: 31 | env = gym.make( 32 | "sat-v0", 33 | args=args, 34 | problems_paths=args.eval_problems_paths, 35 | test_mode=True, 36 | with_restarts=with_restarts, 37 | ) 38 | agent = MiniSATAgent() 39 | print(f"Testing agent {agent}... with_restarts is set to {with_restarts}") 40 | pr = 0 41 | while env.test_to != 0 or pr == 0: 42 | observation = env.reset() 43 | done = False 44 | while not done: 45 | action = agent.act(observation) 46 | observation, reward, done, info = env.step(action, dummy=True) 47 | print( 48 | f'Rollout {pr+1}, steps {env.step_ctr}, num_restarts {info["num_restarts"]}.' 49 | ) 50 | results[env.curr_problem].append(env.step_ctr) 51 | pr += 1 52 | if args.debug and pr >= DEBUG_ROLLOUTS: 53 | break 54 | env.close() 55 | return results, args 56 | 57 | 58 | from os import path 59 | 60 | if __name__ == "__main__": 61 | results, args = main() 62 | for pdir in args.eval_problems_paths.split(":"): 63 | with open(os.path.join(pdir, "METADATA"), "w") as f: 64 | for el in sorted(results.keys()): 65 | cur_dir, pname = path.split(el) 66 | if path.realpath(pdir) == path.realpath(cur_dir): 67 | # no restarts/with restarts 68 | f.write(f"{pname},{results[el][0]},{results[el][1]}\n") 69 | -------------------------------------------------------------------------------- /docker_build.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | docker build -t gqsat . 16 | -------------------------------------------------------------------------------- /docker_run.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | docker run -it -v `pwd`:/home/gqsat_user/gqsat:rw --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=0 gqsat 16 | -------------------------------------------------------------------------------- /dqn.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import numpy as np 16 | import torch 17 | 18 | import os 19 | from collections import deque 20 | import pickle 21 | import copy 22 | import yaml 23 | 24 | from gqsat.utils import build_argparser, evaluate, make_env 25 | from gqsat.models import EncoderCoreDecoder, SatModel 26 | from gqsat.agents import GraphAgent 27 | from gqsat.learners import GraphLearner 28 | from gqsat.buffer import ReplayGraphBuffer 29 | 30 | from tensorboardX import SummaryWriter 31 | 32 | 33 | def save_training_state( 34 | model, 35 | learner, 36 | episodes_done, 37 | transitions_seen, 38 | best_eval_so_far, 39 | args, 40 | in_eval_mode=False, 41 | ): 42 | # save the model 43 | model_path = os.path.join(args.logdir, f"model_{learner.step_ctr}.chkp") 44 | torch.save(model.state_dict(), model_path) 45 | 46 | # save the experience replay 47 | buffer_path = os.path.join(args.logdir, "buffer.pkl") 48 | 49 | with open(buffer_path, "wb") as f: 50 | pickle.dump(learner.buffer, f) 51 | 52 | # save important parameters 53 | train_status = { 54 | "step_ctr": learner.step_ctr, 55 | "latest_model_name": model_path, 56 | "buffer_path": buffer_path, 57 | "args": args, 58 | "episodes_done": episodes_done, 59 | "logdir": args.logdir, 60 | "transitions_seen": transitions_seen, 61 | "optimizer_state_dict": learner.optimizer.state_dict(), 62 | "optimizer_class": type(learner.optimizer), 63 | "best_eval_so_far": best_eval_so_far, 64 | "scheduler_class": type(learner.lr_scheduler), 65 | "scheduler_state_dict": learner.lr_scheduler.state_dict(), 66 | "in_eval_mode": in_eval_mode, 67 | } 68 | status_path = os.path.join(args.logdir, "status.yaml") 69 | 70 | with open(status_path, "w") as f: 71 | yaml.dump(train_status, f, default_flow_style=False) 72 | 73 | return status_path 74 | 75 | 76 | def get_annealed_eps(n_trans, args): 77 | if n_trans < args.init_exploration_steps: 78 | return args.eps_init 79 | if n_trans > args.eps_decay_steps: 80 | return args.eps_final 81 | else: 82 | assert n_trans - args.init_exploration_steps >= 0 83 | return (args.eps_init - args.eps_final) * ( 84 | 1 - (n_trans - args.init_exploration_steps) / args.eps_decay_steps 85 | ) + args.eps_final 86 | 87 | 88 | def arg2activation(activ_str): 89 | if activ_str == "relu": 90 | return torch.nn.ReLU 91 | elif activ_str == "tanh": 92 | return torch.nn.Tanh 93 | elif activ_str == "leaky_relu": 94 | return torch.nn.LeakyReLU 95 | else: 96 | raise ValueError("Unknown activation function") 97 | 98 | 99 | if __name__ == "__main__": 100 | parser = build_argparser() 101 | args = parser.parse_args() 102 | args.device = ( 103 | torch.device("cpu") 104 | if args.no_cuda or not torch.cuda.is_available() 105 | else torch.device("cuda") 106 | ) 107 | 108 | if args.status_dict_path: 109 | # training mode, resuming from the status dict 110 | 111 | # load the train status dict 112 | with open(args.status_dict_path, "r") as f: 113 | train_status = yaml.load(f, Loader=yaml.Loader) 114 | eval_resume_signal = train_status["in_eval_mode"] 115 | # swap the args 116 | args = train_status["args"] 117 | 118 | # load the model 119 | net = SatModel.load_from_yaml(os.path.join(args.logdir, "model.yaml")).to( 120 | args.device 121 | ) 122 | net.load_state_dict(torch.load(train_status["latest_model_name"])) 123 | 124 | target_net = SatModel.load_from_yaml( 125 | os.path.join(args.logdir, "model.yaml") 126 | ).to(args.device) 127 | target_net.load_state_dict(net.state_dict()) 128 | 129 | # load the buffer 130 | with open(train_status["buffer_path"], "rb") as f: 131 | buffer = pickle.load(f) 132 | learner = GraphLearner(net, target_net, buffer, args) 133 | learner.step_ctr = train_status["step_ctr"] 134 | 135 | learner.optimizer = train_status["optimizer_class"]( 136 | net.parameters(), lr=args.lr 137 | ) 138 | learner.optimizer.load_state_dict(train_status["optimizer_state_dict"]) 139 | learner.lr_scheduler = train_status["scheduler_class"]( 140 | learner.optimizer, args.lr_scheduler_frequency, args.lr_scheduler_gamma 141 | ) 142 | learner.lr_scheduler.load_state_dict(train_status["scheduler_state_dict"]) 143 | 144 | # load misc training status params 145 | n_trans = train_status["transitions_seen"] 146 | ep = train_status["episodes_done"] 147 | 148 | env = make_env(args.train_problems_paths, args, test_mode=False) 149 | 150 | agent = GraphAgent(net, args) 151 | 152 | best_eval_so_far = train_status["best_eval_so_far"] 153 | 154 | else: 155 | # training mode, learning from scratch or continuing learning from some previously trained model 156 | writer = SummaryWriter() 157 | args.logdir = writer.logdir 158 | 159 | model_save_path = os.path.join(args.logdir, "model.yaml") 160 | best_eval_so_far = ( 161 | {args.eval_problems_paths: -1} 162 | if not args.eval_separately_on_each 163 | else {k: -1 for k in args.eval_problems_paths.split(":")} 164 | ) 165 | 166 | env = make_env(args.train_problems_paths, args, test_mode=False) 167 | if args.model_dir is not None: 168 | # load an existing model and continue training 169 | net = SatModel.load_from_yaml( 170 | os.path.join(args.model_dir, "model.yaml") 171 | ).to(args.device) 172 | net.load_state_dict( 173 | torch.load(os.path.join(args.model_dir, args.model_checkpoint)) 174 | ) 175 | else: 176 | # learning from scratch 177 | net = EncoderCoreDecoder( 178 | (env.vertex_in_size, env.edge_in_size, env.global_in_size), 179 | core_out_dims=( 180 | args.core_v_out_size, 181 | args.core_e_out_size, 182 | args.core_e_out_size, 183 | ), 184 | out_dims=(2, None, None), 185 | core_steps=args.core_steps, 186 | dec_out_dims=( 187 | args.decoder_v_out_size, 188 | args.decoder_e_out_size, 189 | args.decoder_e_out_size, 190 | ), 191 | encoder_out_dims=( 192 | args.encoder_v_out_size, 193 | args.encoder_e_out_size, 194 | args.encoder_e_out_size, 195 | ), 196 | save_name=model_save_path, 197 | e2v_agg=args.e2v_aggregator, 198 | n_hidden=args.n_hidden, 199 | hidden_size=args.hidden_size, 200 | activation=arg2activation(args.activation), 201 | independent_block_layers=args.independent_block_layers, 202 | ).to(args.device) 203 | print(str(net)) 204 | target_net = copy.deepcopy(net) 205 | 206 | buffer = ReplayGraphBuffer(args, args.buffer_size) 207 | agent = GraphAgent(net, args) 208 | 209 | n_trans = 0 210 | ep = 0 211 | learner = GraphLearner(net, target_net, buffer, args) 212 | eval_resume_signal = False 213 | 214 | print(args.__str__()) 215 | loss = None 216 | 217 | while learner.step_ctr < args.batch_updates: 218 | 219 | ret = 0 220 | obs = env.reset(args.train_time_max_decisions_allowed) 221 | done = env.isSolved 222 | 223 | if args.history_len > 1: 224 | raise NotImplementedError( 225 | "History len greater than one is not implemented for graph nets." 226 | ) 227 | hist_buffer = deque(maxlen=args.history_len) 228 | for _ in range(args.history_len): 229 | hist_buffer.append(obs) 230 | ep_step = 0 231 | 232 | save_flag = False 233 | 234 | while not done: 235 | annealed_eps = get_annealed_eps(n_trans, args) 236 | action = agent.act(hist_buffer, eps=annealed_eps) 237 | next_obs, r, done, _ = env.step(action) 238 | buffer.add_transition(obs, action, r, done) 239 | obs = next_obs 240 | 241 | hist_buffer.append(obs) 242 | ret += r 243 | 244 | if (not n_trans % args.step_freq) and ( 245 | buffer.ctr > max(args.init_exploration_steps, args.bsize + 1) 246 | or buffer.full 247 | ): 248 | step_info = learner.step() 249 | if annealed_eps is not None: 250 | step_info["annealed_eps"] = annealed_eps 251 | 252 | # we increment the step_ctr in the learner.step(), that's why we need to do -1 in tensorboarding 253 | # we do not need to do -1 in checking for frequency since 0 has already passed 254 | 255 | if not learner.step_ctr % args.save_freq: 256 | # save the exact model you evaluated and make another save after the episode ends 257 | # to have proper transitions in the replay buffer to pickle 258 | status_path = save_training_state( 259 | net, 260 | learner, 261 | ep - 1, 262 | n_trans, 263 | best_eval_so_far, 264 | args, 265 | in_eval_mode=eval_resume_signal, 266 | ) 267 | save_flag = True 268 | if ( 269 | args.env_name == "sat-v0" and not learner.step_ctr % args.eval_freq 270 | ) or eval_resume_signal: 271 | scores, _, eval_resume_signal = evaluate( 272 | agent, args, include_train_set=False 273 | ) 274 | 275 | for sc_key, sc_val in scores.items(): 276 | # list can be empty if we hit the time limit for eval 277 | if len(sc_val) > 0: 278 | res_vals = [el for el in sc_val.values()] 279 | median_score = np.nanmedian(res_vals) 280 | if ( 281 | best_eval_so_far[sc_key] < median_score 282 | or best_eval_so_far[sc_key] == -1 283 | ): 284 | best_eval_so_far[sc_key] = median_score 285 | writer.add_scalar( 286 | f"data/median relative score: {sc_key}", 287 | np.nanmedian(res_vals), 288 | learner.step_ctr - 1, 289 | ) 290 | writer.add_scalar( 291 | f"data/mean relative score: {sc_key}", 292 | np.nanmean(res_vals), 293 | learner.step_ctr - 1, 294 | ) 295 | writer.add_scalar( 296 | f"data/max relative score: {sc_key}", 297 | np.nanmax(res_vals), 298 | learner.step_ctr - 1, 299 | ) 300 | for k, v in best_eval_so_far.items(): 301 | writer.add_scalar(k, v, learner.step_ctr - 1) 302 | 303 | for k, v in step_info.items(): 304 | writer.add_scalar(k, v, learner.step_ctr - 1) 305 | 306 | writer.add_scalar("data/num_episodes", ep, learner.step_ctr - 1) 307 | 308 | n_trans += 1 309 | ep_step += 1 310 | 311 | writer.add_scalar("data/ep_return", ret, learner.step_ctr - 1) 312 | writer.add_scalar("data/ep_steps", env.step_ctr, learner.step_ctr - 1) 313 | writer.add_scalar("data/ep_last_reward", r, learner.step_ctr - 1) 314 | print(f"Episode {ep + 1}: Return {ret}.") 315 | ep += 1 316 | 317 | if save_flag: 318 | status_path = save_training_state( 319 | net, 320 | learner, 321 | ep - 1, 322 | n_trans, 323 | best_eval_so_far, 324 | args, 325 | in_eval_mode=eval_resume_signal, 326 | ) 327 | save_flag = False 328 | -------------------------------------------------------------------------------- /evaluate.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import numpy as np 16 | 17 | import torch 18 | import pickle 19 | import yaml 20 | 21 | from gqsat.utils import build_eval_argparser, evaluate 22 | from gqsat.models import SatModel 23 | from gqsat.agents import GraphAgent 24 | 25 | import os 26 | import time 27 | 28 | if __name__ == "__main__": 29 | parser = build_eval_argparser() 30 | eval_args = parser.parse_args() 31 | with open(os.path.join(eval_args.model_dir, "status.yaml"), "r") as f: 32 | train_status = yaml.load(f, Loader=yaml.Loader) 33 | args = train_status["args"] 34 | 35 | # use same args used for training and overwrite them with those asked for eval 36 | for k, v in vars(eval_args).items(): 37 | setattr(args, k, v) 38 | 39 | args.device = ( 40 | torch.device("cpu") 41 | if args.no_cuda or not torch.cuda.is_available() 42 | else torch.device("cuda") 43 | ) 44 | net = SatModel.load_from_yaml(os.path.join(args.model_dir, "model.yaml")).to( 45 | args.device 46 | ) 47 | 48 | # modify core steps for the eval as requested 49 | if args.core_steps != -1: 50 | # -1 if use the same as for training 51 | net.steps = args.core_steps 52 | 53 | net.load_state_dict( 54 | torch.load(os.path.join(args.model_dir, args.model_checkpoint)), strict=False 55 | ) 56 | 57 | agent = GraphAgent(net, args) 58 | 59 | st_time = time.time() 60 | scores, eval_metadata, _ = evaluate(agent, args) 61 | end_time = time.time() 62 | 63 | print( 64 | f"Evaluation is over. It took {end_time - st_time} seconds for the whole procedure" 65 | ) 66 | 67 | # with open("../eval_results.pkl", "wb") as f: 68 | # pickle.dump(scores, f) 69 | 70 | for pset, pset_res in scores.items(): 71 | res_list = [el for el in pset_res.values()] 72 | print(f"Results for {pset}") 73 | print( 74 | f"median_relative_score: {np.nanmedian(res_list)}, mean_relative_score: {np.mean(res_list)}" 75 | ) 76 | -------------------------------------------------------------------------------- /evaluate.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | python3 evaluate.py \ 16 | --logdir ./log \ 17 | --env-name sat-v0 \ 18 | --core-steps -1 \ 19 | --eps-final 0.0 \ 20 | --eval-time-limit 100000000000000 \ 21 | --no_restarts \ 22 | --test_time_max_decisions_allowed 500 \ 23 | --eval-problems-paths PATH_TO_EVAL_DATA \ 24 | --model-dir MODEL_DIR \ 25 | --model-checkpoint CHECKPOINT.chkp 26 | -------------------------------------------------------------------------------- /gqsat/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. -------------------------------------------------------------------------------- /gqsat/agents.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import torch 16 | import numpy as np 17 | from minisat.minisat.gym.MiniSATEnv import VAR_ID_IDX 18 | 19 | 20 | class Agent(object): 21 | def act(self, state): 22 | raise NotImplementedError 23 | 24 | def __str__(self): 25 | raise NotImplementedError 26 | 27 | 28 | class MiniSATAgent(Agent): 29 | """Use MiniSAT agent to solve the problem""" 30 | 31 | def act(self, observation): 32 | return -1 # this will make GymSolver use VSIDS to make a decision 33 | 34 | def __str__(self): 35 | return "" 36 | 37 | 38 | class RandomAgent(Agent): 39 | """Uniformly sample the action space""" 40 | 41 | def __init__(self, action_space): 42 | super().__init__() 43 | self.action_space = action_space 44 | 45 | def act(self, observation): 46 | return self.action_space.sample() 47 | 48 | def __str__(self): 49 | return "" 50 | 51 | 52 | class GraphAgent: 53 | def __init__(self, net, args): 54 | 55 | self.net = net 56 | self.device = args.device 57 | self.debug = args.debug 58 | self.qs_buffer = [] 59 | 60 | def forward(self, hist_buffer): 61 | self.net.eval() 62 | with torch.no_grad(): 63 | vdata, edata, conn, udata = hist_buffer[0] 64 | vdata = torch.tensor(vdata, device=self.device) 65 | edata = torch.tensor(edata, device=self.device) 66 | udata = torch.tensor(udata, device=self.device) 67 | conn = torch.tensor(conn, device=self.device) 68 | vout, eout, _ = self.net(x=vdata, edge_index=conn, edge_attr=edata, u=udata) 69 | res = vout[vdata[:, VAR_ID_IDX] == 1] 70 | 71 | if self.debug: 72 | self.qs_buffer.append(res.flatten().cpu().numpy()) 73 | return res 74 | 75 | def act(self, hist_buffer, eps): 76 | if np.random.random() < eps: 77 | vars_to_decide = np.where(hist_buffer[-1][0][:, VAR_ID_IDX] == 1)[0] 78 | acts = [a for v in vars_to_decide for a in (v * 2, v * 2 + 1)] 79 | return int(np.random.choice(acts)) 80 | else: 81 | qs = self.forward(hist_buffer) 82 | return self.choose_actions(qs) 83 | 84 | def choose_actions(self, qs): 85 | return qs.flatten().argmax().item() 86 | -------------------------------------------------------------------------------- /gqsat/buffer.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import torch 16 | import numpy as np 17 | from gqsat.utils import batch_graphs 18 | 19 | 20 | class ReplayGraphBuffer: 21 | def __init__(self, args, size): 22 | 23 | self.ctr = 0 24 | self.full = False 25 | self.size = size 26 | self.device = args.device 27 | self.dones = torch.ones(size) 28 | self.rewards = torch.zeros(size) 29 | self.actions = torch.zeros(size, dtype=torch.long) 30 | # dtype=object allows to store references to objects of arbitrary size 31 | self.observations = np.zeros((size, 4), dtype=object) 32 | 33 | def add_transition(self, obs, a, r_next, done_next): 34 | self.dones[self.ctr] = int(done_next) 35 | self.rewards[self.ctr] = r_next 36 | self.actions[self.ctr] = a 37 | 38 | # should be vertex_data, edge_data, connectivity, global 39 | for el_idx, el in enumerate(obs): 40 | self.observations[self.ctr][el_idx] = el 41 | 42 | if (self.ctr + 1) % self.size == 0: 43 | self.ctr = 0 44 | self.full = True 45 | else: 46 | self.ctr += 1 47 | 48 | def sample(self, batch_size): 49 | # to be able to grab the next, we use -1 50 | curr_size = self.ctr - 1 if not self.full else self.size - 1 51 | idx = np.random.choice(range(0, curr_size), batch_size) 52 | return ( 53 | self.batch(self.observations[idx]), 54 | self.actions[idx].to(self.device), 55 | self.rewards[idx].to(self.device), 56 | self.batch(self.observations[idx + 1]), 57 | 1.0 - self.dones[idx].to(self.device), 58 | ) 59 | 60 | def batch(self, obs): 61 | return batch_graphs( 62 | [[torch.tensor(i, device=self.device) for i in el] for el in obs], 63 | self.device, 64 | ) 65 | -------------------------------------------------------------------------------- /gqsat/learners.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from torch import nn 16 | from torch_scatter import scatter_max 17 | import torch 18 | from torch.optim.lr_scheduler import StepLR 19 | from minisat.minisat.gym.MiniSATEnv import VAR_ID_IDX 20 | 21 | 22 | class GraphLearner: 23 | def __init__(self, net, target, buffer, args): 24 | self.net = net 25 | self.target = target 26 | self.target.eval() 27 | 28 | self.optimizer = torch.optim.Adam(self.net.parameters(), lr=args.lr) 29 | self.lr_scheduler = StepLR( 30 | self.optimizer, args.lr_scheduler_frequency, args.lr_scheduler_gamma 31 | ) 32 | 33 | if args.loss == "mse": 34 | self.loss = nn.MSELoss() 35 | elif args.loss == "huber": 36 | self.loss = nn.SmoothL1Loss() 37 | else: 38 | raise ValueError("Unknown Loss function.") 39 | 40 | self.bsize = args.bsize 41 | self.gamma = args.gamma 42 | self.buffer = buffer 43 | self.target_update_freq = args.target_update_freq 44 | self.step_ctr = 0 45 | self.grad_clip = args.grad_clip 46 | self.grad_clip_norm_type = args.grad_clip_norm_type 47 | self.device = args.device 48 | 49 | def get_qs(self, states): 50 | vout, eout, _ = self.net( 51 | x=states[0], 52 | edge_index=states[2], 53 | edge_attr=states[1], 54 | v_indices=states[4], 55 | e_indices=states[5], 56 | u=states[6], 57 | ) 58 | return vout[states[0][:, VAR_ID_IDX] == 1], states[3] 59 | 60 | def get_target_qs(self, states): 61 | vout, eout, _ = self.target( 62 | x=states[0], 63 | edge_index=states[2], 64 | edge_attr=states[1], 65 | v_indices=states[4], 66 | e_indices=states[5], 67 | u=states[6], 68 | ) 69 | return vout[states[0][:, VAR_ID_IDX] == 1].detach(), states[3] 70 | 71 | def step(self): 72 | s, a, r, s_next, nonterminals = self.buffer.sample(self.bsize) 73 | # calculate the targets first to optimize the GPU memory 74 | 75 | with torch.no_grad(): 76 | target_qs, target_vertex_sizes = self.get_target_qs(s_next) 77 | idx_for_scatter = [ 78 | [i] * el.item() * 2 for i, el in enumerate(target_vertex_sizes) 79 | ] 80 | idx_for_scatter = torch.tensor( 81 | [el for subl in idx_for_scatter for el in subl], 82 | dtype=torch.long, 83 | device=self.device, 84 | ).flatten() 85 | target_qs = scatter_max(target_qs.flatten(), idx_for_scatter, dim=0)[0] 86 | targets = r + nonterminals * self.gamma * target_qs 87 | 88 | self.net.train() 89 | qs, var_vertex_sizes = self.get_qs(s) 90 | # qs.shape[1] values per node (same num of actions per node) 91 | gather_idx = (var_vertex_sizes * qs.shape[1]).cumsum(0).roll(1) 92 | gather_idx[0] = 0 93 | 94 | qs = qs.flatten()[gather_idx + a] 95 | 96 | loss = self.loss(qs, targets) 97 | 98 | self.optimizer.zero_grad() 99 | loss.backward() 100 | grad_norm = torch.nn.utils.clip_grad_norm_( 101 | self.net.parameters(), self.grad_clip, norm_type=self.grad_clip_norm_type 102 | ) 103 | self.optimizer.step() 104 | 105 | if not self.step_ctr % self.target_update_freq: 106 | self.target.load_state_dict(self.net.state_dict()) 107 | 108 | self.step_ctr += 1 109 | 110 | # I do not know a better solution for getting the lr from the scheduler. 111 | # This will fail for different lrs for different layers. 112 | lr_for_the_update = self.lr_scheduler.get_lr()[0] 113 | 114 | self.lr_scheduler.step() 115 | return { 116 | "loss": loss.item(), 117 | "grad_norm": grad_norm, 118 | "lr": lr_for_the_update, 119 | "average_q": qs.mean(), 120 | } 121 | -------------------------------------------------------------------------------- /gqsat/models.py: -------------------------------------------------------------------------------- 1 | ### The code in this file was originally copied from the Pytorch Geometric library and modified later: 2 | ### https://pytorch-geometric.readthedocs.io/en/latest/_modules/torch_geometric/nn/meta.html#MetaLayer 3 | ### Pytorch geometric license is below 4 | 5 | # Copyright (c) 2019 Matthias Fey 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | # THE SOFTWARE. 24 | 25 | import torch 26 | from torch.nn import Sequential as Seq, Linear as Lin, ReLU, LayerNorm 27 | from torch_scatter import scatter_mean, scatter_add 28 | from torch_geometric.nn.meta import MetaLayer 29 | from torch import nn 30 | import inspect 31 | import yaml 32 | import sys 33 | 34 | 35 | class ModifiedMetaLayer(MetaLayer): 36 | def forward( 37 | self, x, edge_index, edge_attr=None, u=None, v_indices=None, e_indices=None 38 | ): 39 | row, col = edge_index 40 | 41 | if self.edge_model is not None: 42 | edge_attr = self.edge_model(x[row], x[col], edge_attr, u, e_indices) 43 | 44 | if self.node_model is not None: 45 | x = self.node_model(x, edge_index, edge_attr, u, v_indices) 46 | 47 | if self.global_model is not None: 48 | u = self.global_model(x, edge_attr, u, v_indices, e_indices) 49 | 50 | return x, edge_attr, u 51 | 52 | 53 | class SatModel(torch.nn.Module): 54 | def __init__(self, save_name=None): 55 | super().__init__() 56 | if save_name is not None: 57 | self.save_to_yaml(save_name) 58 | 59 | @classmethod 60 | def save_to_yaml(cls, model_name): 61 | # -2 is here because I want to know how many layers below lies the final child and get its init params. 62 | # I do not need nn.Module and 'object' 63 | # this WILL NOT work with multiple inheritance of the leaf children 64 | frame, filename, line_number, function_name, lines, index = inspect.stack()[ 65 | len(cls.mro()) - 2 66 | ] 67 | args, _, _, values = inspect.getargvalues(frame) 68 | 69 | save_dict = { 70 | "class_name": values["self"].__class__.__name__, 71 | "call_args": { 72 | k: values[k] for k in args if k != "self" and k != "save_name" 73 | }, 74 | } 75 | with open(model_name, "w") as f: 76 | yaml.dump(save_dict, f, default_flow_style=False) 77 | 78 | @staticmethod 79 | def load_from_yaml(fname): 80 | with open(fname, "r") as f: 81 | res = yaml.load(f) 82 | return getattr(sys.modules[__name__], res["class_name"])(**res["call_args"]) 83 | 84 | 85 | def get_mlp( 86 | in_size, 87 | out_size, 88 | n_hidden, 89 | hidden_size, 90 | activation=nn.LeakyReLU, 91 | activate_last=True, 92 | layer_norm=True, 93 | ): 94 | arch = [] 95 | l_in = in_size 96 | for l_idx in range(n_hidden): 97 | arch.append(Lin(l_in, hidden_size)) 98 | arch.append(activation()) 99 | l_in = hidden_size 100 | 101 | arch.append(Lin(l_in, out_size)) 102 | 103 | if activate_last: 104 | arch.append(activation()) 105 | 106 | if layer_norm: 107 | arch.append(LayerNorm(out_size)) 108 | 109 | return Seq(*arch) 110 | 111 | 112 | class GraphNet(SatModel): 113 | def __init__( 114 | self, 115 | in_dims, 116 | out_dims, 117 | independent=False, 118 | save_name=None, 119 | e2v_agg="sum", 120 | n_hidden=1, 121 | hidden_size=64, 122 | activation=ReLU, 123 | layer_norm=True, 124 | ): 125 | super().__init__(save_name) 126 | self.e2v_agg = e2v_agg 127 | if e2v_agg not in ["sum", "mean"]: 128 | raise ValueError("Unknown aggregation function.") 129 | 130 | v_in = in_dims[0] 131 | e_in = in_dims[1] 132 | u_in = in_dims[2] 133 | 134 | v_out = out_dims[0] 135 | e_out = out_dims[1] 136 | u_out = out_dims[2] 137 | 138 | if independent: 139 | self.edge_mlp = get_mlp( 140 | e_in, 141 | e_out, 142 | n_hidden, 143 | hidden_size, 144 | activation=activation, 145 | layer_norm=layer_norm, 146 | ) 147 | self.node_mlp = get_mlp( 148 | v_in, 149 | v_out, 150 | n_hidden, 151 | hidden_size, 152 | activation=activation, 153 | layer_norm=layer_norm, 154 | ) 155 | self.global_mlp = get_mlp( 156 | u_in, 157 | u_out, 158 | n_hidden, 159 | hidden_size, 160 | activation=activation, 161 | layer_norm=layer_norm, 162 | ) 163 | else: 164 | self.edge_mlp = get_mlp( 165 | e_in + 2 * v_in + u_in, 166 | e_out, 167 | n_hidden, 168 | hidden_size, 169 | activation=activation, 170 | layer_norm=layer_norm, 171 | ) 172 | self.node_mlp = get_mlp( 173 | v_in + e_out + u_in, 174 | v_out, 175 | n_hidden, 176 | hidden_size, 177 | activation=activation, 178 | layer_norm=layer_norm, 179 | ) 180 | self.global_mlp = get_mlp( 181 | u_in + v_out + e_out, 182 | u_out, 183 | n_hidden, 184 | hidden_size, 185 | activation=activation, 186 | layer_norm=layer_norm, 187 | ) 188 | 189 | self.independent = independent 190 | 191 | def edge_model(src, dest, edge_attr, u=None, e_indices=None): 192 | # source, target: [E, F_x], where E is the number of edges. 193 | # edge_attr: [E, F_e] 194 | if self.independent: 195 | return self.edge_mlp(edge_attr) 196 | 197 | out = torch.cat([src, dest, edge_attr, u[e_indices]], 1) 198 | return self.edge_mlp(out) 199 | 200 | def node_model(x, edge_index, edge_attr, u=None, v_indices=None): 201 | # x: [N, F_x], where N is the number of nodes. 202 | # edge_index: [2, E] with max entry N - 1. 203 | # edge_attr: [E, F_e] 204 | if self.independent: 205 | return self.node_mlp(x) 206 | 207 | row, col = edge_index 208 | if self.e2v_agg == "sum": 209 | out = scatter_add(edge_attr, row, dim=0, dim_size=x.size(0)) 210 | elif self.e2v_agg == "mean": 211 | out = scatter_mean(edge_attr, row, dim=0, dim_size=x.size(0)) 212 | out = torch.cat([x, out, u[v_indices]], dim=1) 213 | return self.node_mlp(out) 214 | 215 | def global_model(x, edge_attr, u, v_indices, e_indices): 216 | if self.independent: 217 | return self.global_mlp(u) 218 | out = torch.cat( 219 | [ 220 | u, 221 | scatter_mean(x, v_indices, dim=0), 222 | scatter_mean(edge_attr, e_indices, dim=0), 223 | ], 224 | dim=1, 225 | ) 226 | return self.global_mlp(out) 227 | 228 | self.op = ModifiedMetaLayer(edge_model, node_model, global_model) 229 | 230 | def forward( 231 | self, x, edge_index, edge_attr=None, u=None, v_indices=None, e_indices=None 232 | ): 233 | return self.op(x, edge_index, edge_attr, u, v_indices, e_indices) 234 | 235 | 236 | class EncoderCoreDecoder(SatModel): 237 | def __init__( 238 | self, 239 | in_dims, 240 | core_out_dims, 241 | out_dims, 242 | core_steps=1, 243 | encoder_out_dims=None, 244 | dec_out_dims=None, 245 | save_name=None, 246 | e2v_agg="sum", 247 | n_hidden=1, 248 | hidden_size=64, 249 | activation=ReLU, 250 | independent_block_layers=1, 251 | ): 252 | super().__init__(save_name) 253 | # all dims are tuples with (v,e) feature sizes 254 | self.steps = core_steps 255 | # if dec_out_dims is None, there will not be a decoder 256 | self.in_dims = in_dims 257 | self.core_out_dims = core_out_dims 258 | self.dec_out_dims = dec_out_dims 259 | 260 | self.layer_norm = True 261 | 262 | self.encoder = None 263 | if encoder_out_dims is not None: 264 | self.encoder = GraphNet( 265 | in_dims, 266 | encoder_out_dims, 267 | independent=True, 268 | n_hidden=independent_block_layers, 269 | hidden_size=hidden_size, 270 | activation=activation, 271 | layer_norm=self.layer_norm, 272 | ) 273 | 274 | core_in_dims = in_dims if self.encoder is None else encoder_out_dims 275 | 276 | self.core = GraphNet( 277 | ( 278 | core_in_dims[0] + core_out_dims[0], 279 | core_in_dims[1] + core_out_dims[1], 280 | core_in_dims[2] + core_out_dims[2], 281 | ), 282 | core_out_dims, 283 | e2v_agg=e2v_agg, 284 | n_hidden=n_hidden, 285 | hidden_size=hidden_size, 286 | activation=activation, 287 | layer_norm=self.layer_norm, 288 | ) 289 | 290 | if dec_out_dims is not None: 291 | self.decoder = GraphNet( 292 | core_out_dims, 293 | dec_out_dims, 294 | independent=True, 295 | n_hidden=independent_block_layers, 296 | hidden_size=hidden_size, 297 | activation=activation, 298 | layer_norm=self.layer_norm, 299 | ) 300 | 301 | pre_out_dims = core_out_dims if self.decoder is None else dec_out_dims 302 | 303 | self.vertex_out_transform = ( 304 | Lin(pre_out_dims[0], out_dims[0]) if out_dims[0] is not None else None 305 | ) 306 | self.edge_out_transform = ( 307 | Lin(pre_out_dims[1], out_dims[1]) if out_dims[1] is not None else None 308 | ) 309 | self.global_out_transform = ( 310 | Lin(pre_out_dims[2], out_dims[2]) if out_dims[2] is not None else None 311 | ) 312 | 313 | def get_init_state(self, n_v, n_e, n_u, device): 314 | return ( 315 | torch.zeros((n_v, self.core_out_dims[0]), device=device), 316 | torch.zeros((n_e, self.core_out_dims[1]), device=device), 317 | torch.zeros((n_u, self.core_out_dims[2]), device=device), 318 | ) 319 | 320 | def forward(self, x, edge_index, edge_attr, u, v_indices=None, e_indices=None): 321 | # if v_indices and e_indices are both None, then we have only one graph without a batch 322 | if v_indices is None and e_indices is None: 323 | v_indices = torch.zeros(x.shape[0], dtype=torch.long, device=x.device) 324 | e_indices = torch.zeros( 325 | edge_attr.shape[0], dtype=torch.long, device=edge_attr.device 326 | ) 327 | 328 | if self.encoder is not None: 329 | x, edge_attr, u = self.encoder( 330 | x, edge_index, edge_attr, u, v_indices, e_indices 331 | ) 332 | 333 | latent0 = (x, edge_attr, u) 334 | latent = self.get_init_state( 335 | x.shape[0], edge_attr.shape[0], u.shape[0], x.device 336 | ) 337 | for st in range(self.steps): 338 | latent = self.core( 339 | torch.cat([latent0[0], latent[0]], dim=1), 340 | edge_index, 341 | torch.cat([latent0[1], latent[1]], dim=1), 342 | torch.cat([latent0[2], latent[2]], dim=1), 343 | v_indices, 344 | e_indices, 345 | ) 346 | 347 | if self.decoder is not None: 348 | latent = self.decoder( 349 | latent[0], edge_index, latent[1], latent[2], v_indices, e_indices 350 | ) 351 | 352 | v_out = ( 353 | latent[0] 354 | if self.vertex_out_transform is None 355 | else self.vertex_out_transform(latent[0]) 356 | ) 357 | e_out = ( 358 | latent[1] 359 | if self.edge_out_transform is None 360 | else self.edge_out_transform(latent[1]) 361 | ) 362 | u_out = ( 363 | latent[2] 364 | if self.global_out_transform is None 365 | else self.global_out_transform(latent[2]) 366 | ) 367 | return v_out, e_out, u_out 368 | -------------------------------------------------------------------------------- /minisat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ##################################################################################################################### 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ##################################################################################################################### 5 | # MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 6 | # Copyright (c) 2007-2010 Niklas Sorensson 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a 9 | # copy of this software and associated documentation files (the 10 | # "Software"), to deal in the Software without restriction, including 11 | # without limitation the rights to use, copy, modify, merge, publish, 12 | # distribute, sublicense, and/or sell copies of the Software, and to 13 | # permit persons to whom the Software is furnished to do so, subject to 14 | # the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | 28 | cmake_minimum_required(VERSION 2.6 FATAL_ERROR) 29 | 30 | project(minisat) 31 | 32 | #-------------------------------------------------------------------------------------------------- 33 | # Configurable options: 34 | 35 | option(STATIC_BINARIES "Link binaries statically." ON) 36 | option(USE_SORELEASE "Use SORELEASE in shared library filename." ON) 37 | 38 | #-------------------------------------------------------------------------------------------------- 39 | # Library version: 40 | 41 | set(MINISAT_SOMAJOR 2) 42 | set(MINISAT_SOMINOR 1) 43 | set(MINISAT_SORELEASE 0) 44 | 45 | # Compute VERSION and SOVERSION: 46 | if (USE_SORELEASE) 47 | set(MINISAT_VERSION ${MINISAT_SOMAJOR}.${MINISAT_SOMINOR}.${MINISAT_SORELEASE}) 48 | else() 49 | set(MINISAT_VERSION ${MINISAT_SOMAJOR}.${MINISAT_SOMINOR}) 50 | endif() 51 | set(MINISAT_SOVERSION ${MINISAT_SOMAJOR}) 52 | 53 | #-------------------------------------------------------------------------------------------------- 54 | # Dependencies: 55 | 56 | find_package(ZLIB) 57 | include_directories(${ZLIB_INCLUDE_DIR}) 58 | include_directories(${minisat_SOURCE_DIR}) 59 | 60 | #-------------------------------------------------------------------------------------------------- 61 | # Compile flags: 62 | 63 | add_definitions(-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS) 64 | 65 | #-------------------------------------------------------------------------------------------------- 66 | # Build Targets: 67 | 68 | set(MINISAT_LIB_SOURCES 69 | minisat/utils/Options.cc 70 | minisat/utils/System.cc 71 | minisat/core/Solver.cc 72 | minisat/simp/SimpSolver.cc) 73 | 74 | add_library(minisat-lib-static STATIC ${MINISAT_LIB_SOURCES}) 75 | add_library(minisat-lib-shared SHARED ${MINISAT_LIB_SOURCES}) 76 | 77 | target_link_libraries(minisat-lib-shared ${ZLIB_LIBRARY}) 78 | target_link_libraries(minisat-lib-static ${ZLIB_LIBRARY}) 79 | 80 | add_executable(minisat_core minisat/core/Main.cc) 81 | add_executable(minisat_simp minisat/simp/Main.cc) 82 | 83 | if(STATIC_BINARIES) 84 | target_link_libraries(minisat_core minisat-lib-static) 85 | target_link_libraries(minisat_simp minisat-lib-static) 86 | else() 87 | target_link_libraries(minisat_core minisat-lib-shared) 88 | target_link_libraries(minisat_simp minisat-lib-shared) 89 | endif() 90 | 91 | set_target_properties(minisat-lib-static PROPERTIES OUTPUT_NAME "minisat") 92 | set_target_properties(minisat-lib-shared 93 | PROPERTIES 94 | OUTPUT_NAME "minisat" 95 | VERSION ${MINISAT_VERSION} 96 | SOVERSION ${MINISAT_SOVERSION}) 97 | 98 | set_target_properties(minisat_simp PROPERTIES OUTPUT_NAME "minisat") 99 | 100 | #-------------------------------------------------------------------------------------------------- 101 | # Installation targets: 102 | 103 | install(TARGETS minisat-lib-static minisat-lib-shared minisat_core minisat_simp 104 | RUNTIME DESTINATION bin 105 | LIBRARY DESTINATION lib 106 | ARCHIVE DESTINATION lib) 107 | 108 | install(DIRECTORY minisat/mtl minisat/utils minisat/core minisat/simp 109 | DESTINATION include/minisat 110 | FILES_MATCHING PATTERN "*.h") 111 | -------------------------------------------------------------------------------- /minisat/LICENSE: -------------------------------------------------------------------------------- 1 | ##################################################################################################################### 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ##################################################################################################################### 5 | 6 | MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 7 | Copyright (c) 2007-2010 Niklas Sorensson 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a 10 | copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included 18 | in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /minisat/Makefile: -------------------------------------------------------------------------------- 1 | ##################################################################################################################### 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ##################################################################################################################### 5 | # MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 6 | # Copyright (c) 2007-2010 Niklas Sorensson 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a 9 | # copy of this software and associated documentation files (the 10 | # "Software"), to deal in the Software without restriction, including 11 | # without limitation the rights to use, copy, modify, merge, publish, 12 | # distribute, sublicense, and/or sell copies of the Software, and to 13 | # permit persons to whom the Software is furnished to do so, subject to 14 | # the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | # 27 | ################################################################################################### 28 | 29 | .PHONY: r d p sh cr cd cp csh lr ld lp lsh config all install install-headers install-lib\ 30 | install-bin clean distclean 31 | all: r lr lsh 32 | 33 | ## Load Previous Configuration #################################################################### 34 | 35 | -include config.mk 36 | 37 | ## Configurable options ########################################################################### 38 | 39 | # Directory to store object files, libraries, executables, and dependencies: 40 | BUILD_DIR ?= build 41 | 42 | # Include debug-symbols in release builds 43 | MINISAT_RELSYM ?= -g 44 | 45 | # Sets of compile flags for different build types 46 | MINISAT_REL ?= -O3 -D NDEBUG 47 | MINISAT_DEB ?= -O0 -D DEBUG 48 | MINISAT_PRF ?= -O3 -D NDEBUG 49 | MINISAT_FPIC ?= -fpic 50 | 51 | # GNU Standard Install Prefix 52 | prefix ?= /usr/local 53 | 54 | ## Write Configuration ########################################################################### 55 | 56 | config: 57 | @( echo 'BUILD_DIR?=$(BUILD_DIR)' ; \ 58 | echo 'MINISAT_RELSYM?=$(MINISAT_RELSYM)' ; \ 59 | echo 'MINISAT_REL?=$(MINISAT_REL)' ; \ 60 | echo 'MINISAT_DEB?=$(MINISAT_DEB)' ; \ 61 | echo 'MINISAT_PRF?=$(MINISAT_PRF)' ; \ 62 | echo 'MINISAT_FPIC?=$(MINISAT_FPIC)' ; \ 63 | echo 'prefix?=$(prefix)' ) > config.mk 64 | 65 | ## Configurable options end ####################################################################### 66 | 67 | INSTALL ?= install 68 | 69 | # GNU Standard Install Variables 70 | exec_prefix ?= $(prefix) 71 | includedir ?= $(prefix)/include 72 | bindir ?= $(exec_prefix)/bin 73 | libdir ?= $(exec_prefix)/lib 74 | datarootdir ?= $(prefix)/share 75 | mandir ?= $(datarootdir)/man 76 | 77 | # Target file names 78 | MINISAT = minisat# Name of MiniSat main executable. 79 | MINISAT_CORE = minisat_core# Name of simplified MiniSat executable (only core solver support). 80 | MINISAT_SLIB = lib$(MINISAT).a# Name of MiniSat static library. 81 | MINISAT_DLIB = lib$(MINISAT).so# Name of MiniSat shared library. 82 | 83 | # Shared Library Version 84 | SOMAJOR=2 85 | SOMINOR=1 86 | SORELEASE?=.0# Declare empty to leave out from library file name. 87 | 88 | MINISAT_CXXFLAGS = -I. -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS -Wall -Wno-parentheses -Wextra 89 | MINISAT_LDFLAGS = -Wall -lz 90 | 91 | ECHO=@echo 92 | ifeq ($(VERB),) 93 | VERB=@ 94 | else 95 | VERB= 96 | endif 97 | 98 | SRCS = $(wildcard minisat/core/*.cc) $(wildcard minisat/simp/*.cc) $(wildcard minisat/utils/*.cc) $(wildcard minisat/gym/*.cc) 99 | HDRS = $(wildcard minisat/mtl/*.h) $(wildcard minisat/core/*.h) $(wildcard minisat/simp/*.h) $(wildcard minisat/utils/*.h) $(wildcard minisat/gym/*.h) 100 | OBJS = $(filter-out %Main.o, $(SRCS:.cc=.o)) 101 | 102 | r: $(BUILD_DIR)/release/bin/$(MINISAT) 103 | d: $(BUILD_DIR)/debug/bin/$(MINISAT) 104 | p: $(BUILD_DIR)/profile/bin/$(MINISAT) 105 | sh: $(BUILD_DIR)/dynamic/bin/$(MINISAT) 106 | 107 | cr: $(BUILD_DIR)/release/bin/$(MINISAT_CORE) 108 | cd: $(BUILD_DIR)/debug/bin/$(MINISAT_CORE) 109 | cp: $(BUILD_DIR)/profile/bin/$(MINISAT_CORE) 110 | csh: $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE) 111 | 112 | lr: $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 113 | ld: $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 114 | lp: $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 115 | lsh: $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) 116 | 117 | ## Build-type Compile-flags: 118 | $(BUILD_DIR)/release/%.o: MINISAT_CXXFLAGS +=$(MINISAT_REL) $(MINISAT_RELSYM) 119 | $(BUILD_DIR)/debug/%.o: MINISAT_CXXFLAGS +=$(MINISAT_DEB) -g 120 | $(BUILD_DIR)/profile/%.o: MINISAT_CXXFLAGS +=$(MINISAT_PRF) -pg 121 | $(BUILD_DIR)/dynamic/%.o: MINISAT_CXXFLAGS +=$(MINISAT_REL) $(MINISAT_FPIC) 122 | 123 | ## Build-type Link-flags: 124 | $(BUILD_DIR)/profile/bin/$(MINISAT): MINISAT_LDFLAGS += -pg 125 | $(BUILD_DIR)/release/bin/$(MINISAT): MINISAT_LDFLAGS += --static $(MINISAT_RELSYM) 126 | $(BUILD_DIR)/profile/bin/$(MINISAT_CORE): MINISAT_LDFLAGS += -pg 127 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE): MINISAT_LDFLAGS += --static $(MINISAT_RELSYM) 128 | 129 | ## Executable dependencies 130 | $(BUILD_DIR)/release/bin/$(MINISAT): $(BUILD_DIR)/release/minisat/simp/Main.o $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 131 | $(BUILD_DIR)/debug/bin/$(MINISAT): $(BUILD_DIR)/debug/minisat/simp/Main.o $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 132 | $(BUILD_DIR)/profile/bin/$(MINISAT): $(BUILD_DIR)/profile/minisat/simp/Main.o $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 133 | # need the main-file be compiled with fpic? 134 | $(BUILD_DIR)/dynamic/bin/$(MINISAT): $(BUILD_DIR)/dynamic/minisat/simp/Main.o $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 135 | 136 | ## Executable dependencies (core-version) 137 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE): $(BUILD_DIR)/release/minisat/core/Main.o $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) 138 | $(BUILD_DIR)/debug/bin/$(MINISAT_CORE): $(BUILD_DIR)/debug/minisat/core/Main.o $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 139 | $(BUILD_DIR)/profile/bin/$(MINISAT_CORE): $(BUILD_DIR)/profile/minisat/core/Main.o $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB) 140 | # need the main-file be compiled with fpic? 141 | $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE): $(BUILD_DIR)/dynamic/minisat/core/Main.o $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 142 | 143 | ## Library dependencies 144 | $(BUILD_DIR)/release/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/release/$(o)) 145 | $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/debug/$(o)) 146 | $(BUILD_DIR)/profile/lib/$(MINISAT_SLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/profile/$(o)) 147 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 148 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 149 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB): $(foreach o,$(OBJS),$(BUILD_DIR)/dynamic/$(o)) 150 | 151 | ## Compile rules (these should be unified, buit I have not yet found a way which works in GNU Make) 152 | $(BUILD_DIR)/release/%.o: %.cc 153 | $(ECHO) Compiling: $@ 154 | $(VERB) mkdir -p $(dir $@) 155 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/release/$*.d 156 | 157 | $(BUILD_DIR)/profile/%.o: %.cc 158 | $(ECHO) Compiling: $@ 159 | $(VERB) mkdir -p $(dir $@) 160 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/profile/$*.d 161 | 162 | $(BUILD_DIR)/debug/%.o: %.cc 163 | $(ECHO) Compiling: $@ 164 | $(VERB) mkdir -p $(dir $@) 165 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/debug/$*.d 166 | 167 | $(BUILD_DIR)/dynamic/%.o: %.cc 168 | $(ECHO) Compiling: $@ 169 | $(VERB) mkdir -p $(dir $@) 170 | $(VERB) $(CXX) $(MINISAT_CXXFLAGS) $(CXXFLAGS) -c -o $@ $< -MMD -MF $(BUILD_DIR)/dynamic/$*.d 171 | 172 | ## Linking rule 173 | $(BUILD_DIR)/release/bin/$(MINISAT) $(BUILD_DIR)/debug/bin/$(MINISAT) $(BUILD_DIR)/profile/bin/$(MINISAT) $(BUILD_DIR)/dynamic/bin/$(MINISAT)\ 174 | $(BUILD_DIR)/release/bin/$(MINISAT_CORE) $(BUILD_DIR)/debug/bin/$(MINISAT_CORE) $(BUILD_DIR)/profile/bin/$(MINISAT_CORE) $(BUILD_DIR)/dynamic/bin/$(MINISAT_CORE): 175 | $(ECHO) Linking Binary: $@ 176 | $(VERB) mkdir -p $(dir $@) 177 | $(VERB) $(CXX) $^ $(MINISAT_LDFLAGS) $(LDFLAGS) -o $@ 178 | 179 | ## Static Library rule 180 | %/lib/$(MINISAT_SLIB): 181 | $(ECHO) Linking Static Library: $@ 182 | $(VERB) mkdir -p $(dir $@) 183 | $(VERB) $(AR) -rcs $@ $^ 184 | 185 | ## Shared Library rule 186 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 187 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 188 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB): 189 | $(ECHO) Linking Shared Library: $@ 190 | $(VERB) mkdir -p $(dir $@) 191 | $(VERB) $(CXX) $(MINISAT_LDFLAGS) $(LDFLAGS) -o $@ -shared -Wl,-soname,$(MINISAT_DLIB).$(SOMAJOR) $^ 192 | $(VERB) ln -sf $(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR) 193 | $(VERB) ln -sf $(MINISAT_DLIB).$(SOMAJOR) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 194 | 195 | install: install-headers install-lib install-bin 196 | install-debug: install-headers install-lib-debug 197 | 198 | install-headers: 199 | # Create directories 200 | $(INSTALL) -d $(DESTDIR)$(includedir)/minisat 201 | for dir in mtl utils core simp gym; do \ 202 | $(INSTALL) -d $(DESTDIR)$(includedir)/minisat/$$dir ; \ 203 | done 204 | # Install headers 205 | for h in $(HDRS) ; do \ 206 | $(INSTALL) -m 644 $$h $(DESTDIR)$(includedir)/$$h ; \ 207 | done 208 | 209 | install-lib-debug: $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) 210 | $(INSTALL) -d $(DESTDIR)$(libdir) 211 | $(INSTALL) -m 644 $(BUILD_DIR)/debug/lib/$(MINISAT_SLIB) $(DESTDIR)$(libdir) 212 | 213 | install-lib: $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) 214 | $(INSTALL) -d $(DESTDIR)$(libdir) 215 | $(INSTALL) -m 644 $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(DESTDIR)$(libdir) 216 | ln -sf $(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(DESTDIR)$(libdir)/$(MINISAT_DLIB).$(SOMAJOR) 217 | ln -sf $(MINISAT_DLIB).$(SOMAJOR) $(DESTDIR)$(libdir)/$(MINISAT_DLIB) 218 | $(INSTALL) -m 644 $(BUILD_DIR)/release/lib/$(MINISAT_SLIB) $(DESTDIR)$(libdir) 219 | 220 | install-bin: $(BUILD_DIR)/dynamic/bin/$(MINISAT) 221 | $(INSTALL) -d $(DESTDIR)$(bindir) 222 | $(INSTALL) -m 755 $(BUILD_DIR)/dynamic/bin/$(MINISAT) $(DESTDIR)$(bindir) 223 | 224 | python-wrap: $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE) $(SRCS) 225 | # Graph-Q-SAT UPD: bump python version 226 | g++ -O2 -fPIC -c minisat/gym/GymSolver_wrap.cxx -o minisat/gym/GymSolver_wrap.o -I. -I/usr/include/python3.6 227 | g++ -shared -o minisat/gym/_GymSolver.so $(foreach o,$(OBJS),$(BUILD_DIR)/dynamic/$(o)) minisat/gym/GymSolver_wrap.o /usr/lib/x86_64-linux-gnu/libz.so 228 | 229 | clean: 230 | rm -f $(foreach t, release debug profile dynamic, $(foreach o, $(SRCS:.cc=.o), $(BUILD_DIR)/$t/$o)) \ 231 | $(foreach t, release debug profile dynamic, $(foreach d, $(SRCS:.cc=.d), $(BUILD_DIR)/$t/$d)) \ 232 | $(foreach t, release debug profile dynamic, $(BUILD_DIR)/$t/bin/$(MINISAT_CORE) $(BUILD_DIR)/$t/bin/$(MINISAT)) \ 233 | $(foreach t, release debug profile, $(BUILD_DIR)/$t/lib/$(MINISAT_SLIB)) \ 234 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR).$(SOMINOR)$(SORELEASE)\ 235 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB).$(SOMAJOR)\ 236 | $(BUILD_DIR)/dynamic/lib/$(MINISAT_DLIB) 237 | 238 | distclean: clean 239 | rm -f config.mk 240 | 241 | ## Include generated dependencies 242 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/release/$s) 243 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/debug/$s) 244 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/profile/$s) 245 | -include $(foreach s, $(SRCS:.cc=.d), $(BUILD_DIR)/dynamic/$s) 246 | -------------------------------------------------------------------------------- /minisat/__init__.py: -------------------------------------------------------------------------------- 1 | ################################################################################################################################# 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ################################################################################################################################# 5 | 6 | # MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 7 | # Copyright (c) 2007-2010 Niklas Sorensson 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a 10 | # copy of this software and associated documentation files (the 11 | # "Software"), to deal in the Software without restriction, including 12 | # without limitation the rights to use, copy, modify, merge, publish, 13 | # distribute, sublicense, and/or sell copies of the Software, and to 14 | # permit persons to whom the Software is furnished to do so, subject to 15 | # the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included 18 | # in all copies or substantial portions of the Software. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 24 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | from .minisat.gym.MiniSATEnv import gym_sat_Env 29 | 30 | from gym.envs.registration import register 31 | 32 | # Graph-Q-SAT UPD: register the sat environment 33 | register(id="sat-v0", entry_point="minisat.minisat.gym.MiniSATEnv:gym_sat_Env") 34 | -------------------------------------------------------------------------------- /minisat/minisat/__init__.py: -------------------------------------------------------------------------------- 1 | ################################################################################################################################# 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ################################################################################################################################# 5 | # MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 6 | # Copyright (c) 2007-2010 Niklas Sorensson 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a 9 | # copy of this software and associated documentation files (the 10 | # "Software"), to deal in the Software without restriction, including 11 | # without limitation the rights to use, copy, modify, merge, publish, 12 | # distribute, sublicense, and/or sell copies of the Software, and to 13 | # permit persons to whom the Software is furnished to do so, subject to 14 | # the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /minisat/minisat/core/Dimacs.h: -------------------------------------------------------------------------------- 1 | /* 2 | ######################################################################################################################### 3 | # All the files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat# 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ######################################################################################################################### 6 | */ 7 | 8 | 9 | /****************************************************************************************[Dimacs.h] 10 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 11 | Copyright (c) 2007-2010, Niklas Sorensson 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 14 | associated documentation files (the "Software"), to deal in the Software without restriction, 15 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 16 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all copies or 20 | substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 23 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 25 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 26 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | **************************************************************************************************/ 28 | 29 | #ifndef Minisat_Dimacs_h 30 | #define Minisat_Dimacs_h 31 | 32 | #include 33 | 34 | #include "minisat/utils/ParseUtils.h" 35 | #include "minisat/core/SolverTypes.h" 36 | 37 | namespace Minisat { 38 | 39 | //================================================================================================= 40 | // DIMACS Parser: 41 | 42 | template 43 | static void readClause(B& in, Solver& S, vec& lits) { 44 | int parsed_lit, var; 45 | lits.clear(); 46 | for (;;){ 47 | parsed_lit = parseInt(in); 48 | if (parsed_lit == 0) break; 49 | var = abs(parsed_lit)-1; 50 | while (var >= S.nVars()) S.newVar(); 51 | lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) ); 52 | } 53 | } 54 | 55 | template 56 | static void parse_DIMACS_main(B& in, Solver& S, bool strictp = false) { 57 | vec lits; 58 | int vars = 0; 59 | int clauses = 0; 60 | int cnt = 0; 61 | for (;;){ 62 | skipWhitespace(in); 63 | if (*in == EOF) break; 64 | if (*in == '%') break; 65 | else if (*in == 'p'){ 66 | if (eagerMatch(in, "p cnf")){ 67 | vars = parseInt(in); 68 | clauses = parseInt(in); 69 | // SATRACE'06 hack 70 | // if (clauses > 4000000) 71 | // S.eliminate(true); 72 | }else{ 73 | printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 74 | } 75 | } else if (*in == 'c' || *in == 'p') 76 | skipLine(in); 77 | else{ 78 | cnt++; 79 | readClause(in, S, lits); 80 | S.addClause_(lits); } 81 | } 82 | if (strictp && cnt != clauses) 83 | printf("PARSE ERROR! DIMACS header mismatch: wrong number of clauses\n"); 84 | } 85 | 86 | // Inserts problem into solver. 87 | // 88 | template 89 | static void parse_DIMACS(gzFile input_stream, Solver& S, bool strictp = false) { 90 | StreamBuffer in(input_stream); 91 | parse_DIMACS_main(in, S, strictp); } 92 | 93 | //================================================================================================= 94 | } 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /minisat/minisat/core/Main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ######################################################################################################################### 3 | # All the files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat# 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ######################################################################################################################### 6 | */ 7 | 8 | /*****************************************************************************************[Main.cc] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #include 29 | #include 30 | 31 | #include "minisat/utils/System.h" 32 | #include "minisat/utils/ParseUtils.h" 33 | #include "minisat/utils/Options.h" 34 | #include "minisat/core/Dimacs.h" 35 | #include "minisat/core/Solver.h" 36 | 37 | using namespace Minisat; 38 | 39 | //================================================================================================= 40 | 41 | 42 | static Solver* solver; 43 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 44 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 45 | static void SIGINT_interrupt(int) { solver->interrupt(); } 46 | 47 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 48 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 49 | // functions are guarded by locks for multithreaded use). 50 | static void SIGINT_exit(int) { 51 | printf("\n"); printf("*** INTERRUPTED ***\n"); 52 | if (solver->verbosity > 0){ 53 | solver->printStats(); 54 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 55 | _exit(1); } 56 | 57 | 58 | //================================================================================================= 59 | // Main: 60 | 61 | 62 | int main(int argc, char** argv) 63 | { 64 | try { 65 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 66 | setX86FPUPrecision(); 67 | 68 | // Extra options: 69 | // 70 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 71 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", 0, IntRange(0, INT32_MAX)); 72 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", 0, IntRange(0, INT32_MAX)); 73 | BoolOption strictp("MAIN", "strict", "Validate DIMACS header during parsing.", false); 74 | 75 | parseOptions(argc, argv, true); 76 | 77 | Solver S; 78 | double initial_time = cpuTime(); 79 | 80 | S.verbosity = verb; 81 | 82 | solver = &S; 83 | // Use signal handlers that forcibly quit until the solver will be able to respond to 84 | // interrupts: 85 | sigTerm(SIGINT_exit); 86 | 87 | // Try to set resource limits: 88 | if (cpu_lim != 0) limitTime(cpu_lim); 89 | if (mem_lim != 0) limitMemory(mem_lim); 90 | 91 | if (argc == 1) 92 | printf("Reading from standard input... Use '--help' for help.\n"); 93 | 94 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 95 | if (in == NULL) 96 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 97 | 98 | if (S.verbosity > 0){ 99 | printf("============================[ Problem Statistics ]=============================\n"); 100 | printf("| |\n"); } 101 | 102 | parse_DIMACS(in, S, (bool)strictp); 103 | gzclose(in); 104 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 105 | 106 | if (S.verbosity > 0){ 107 | printf("| Number of variables: %12d |\n", S.nVars()); 108 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 109 | 110 | double parsed_time = cpuTime(); 111 | if (S.verbosity > 0){ 112 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 113 | printf("| |\n"); } 114 | 115 | // Change to signal-handlers that will only notify the solver and allow it to terminate 116 | // voluntarily: 117 | sigTerm(SIGINT_interrupt); 118 | 119 | if (!S.simplify()){ 120 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 121 | if (S.verbosity > 0){ 122 | printf("===============================================================================\n"); 123 | printf("Solved by unit propagation\n"); 124 | S.printStats(); 125 | printf("\n"); } 126 | printf("UNSATISFIABLE\n"); 127 | exit(20); 128 | } 129 | 130 | vec dummy; 131 | lbool ret = S.solveLimited(dummy); 132 | if (S.verbosity > 0){ 133 | S.printStats(); 134 | printf("\n"); } 135 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 136 | if (res != NULL){ 137 | if (ret == l_True){ 138 | fprintf(res, "SAT\n"); 139 | for (int i = 0; i < S.nVars(); i++) 140 | if (S.model[i] != l_Undef) 141 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); 142 | fprintf(res, " 0\n"); 143 | }else if (ret == l_False) 144 | fprintf(res, "UNSAT\n"); 145 | else 146 | fprintf(res, "INDET\n"); 147 | fclose(res); 148 | } 149 | 150 | #ifdef NDEBUG 151 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 152 | #else 153 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 154 | #endif 155 | } catch (OutOfMemoryException&){ 156 | printf("===============================================================================\n"); 157 | printf("INDETERMINATE\n"); 158 | exit(0); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /minisat/minisat/gym/GymSolver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | /***********************************************************************************[SolverTypes.h] 7 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 8 | Copyright (c) 2007-2010, Niklas Sorensson 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 11 | associated documentation files (the "Software"), to deal in the Software without restriction, 12 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 13 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or 17 | substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 20 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 23 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | **************************************************************************************************/ 25 | 26 | #include 27 | #include 28 | 29 | #include "minisat/utils/System.h" 30 | #include "minisat/utils/ParseUtils.h" 31 | #include "minisat/utils/Options.h" 32 | #include "minisat/core/Dimacs.h" 33 | #include "minisat/simp/SimpSolver.h" 34 | #include "minisat/gym/GymSolver.h" 35 | 36 | using namespace Minisat; 37 | 38 | // Graph-Q-SAT UPD: Add additional parameters for the environment generation. 39 | GymSolver::GymSolver(char* satProb, bool with_restarts, int max_decision_cap) { 40 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 0, IntRange(0, 2)); 41 | S.verbosity = verb; 42 | S.with_restarts = with_restarts; 43 | S.max_decision_cap = max_decision_cap; 44 | gzFile in = gzopen(satProb, "rb"); 45 | if (in == NULL) { 46 | printf("ERROR! Could not open file: %s\n", satProb); 47 | exit(1); 48 | } 49 | parse_DIMACS(in, S, true); 50 | gzclose(in); 51 | 52 | S.eliminate(true); 53 | if (!S.okay()){ 54 | printf("ERROR! SAT problem from file: %s is UNSAT by simplification\n", satProb); 55 | exit(1); 56 | } 57 | 58 | // Comments by Fei: Now the solveLimited() function really just initialize the problem. It needs steps to finish up! 59 | vec dummy; 60 | S.solveLimited(dummy); 61 | 62 | } 63 | 64 | void GymSolver::step(int decision) { 65 | if (decision == 32767) { 66 | S.agent_decision = S.default_pickLit(); // if the decision is MaxInt number, let the minisat decide! 67 | } else { 68 | S.agent_decision = mkLit(abs(decision)-1, decision < 0); 69 | } 70 | S.step(); 71 | } 72 | 73 | double GymSolver::getReward() { 74 | return S.env_reward; 75 | } 76 | 77 | bool GymSolver::getDone() { 78 | return !S.env_hold; 79 | } 80 | 81 | // Graph-Q-SAT UPD: Get metadata/clauses/activities helpers. 82 | std::vector* GymSolver::getMetadata() { 83 | return &S.env_state_metadata; 84 | } 85 | 86 | std::vector* GymSolver::getAssignments() { 87 | return &S.env_state_assignments; 88 | } 89 | 90 | std::vector >* GymSolver::getClauses() { 91 | return &S.env_state_clauses; 92 | } 93 | 94 | std::vector* GymSolver::getActivities() { 95 | return &S.env_state_activities; 96 | } 97 | -------------------------------------------------------------------------------- /minisat/minisat/gym/GymSolver.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | /***********************************************************************************[SolverTypes.h] 8 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 9 | Copyright (c) 2007-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | #ifndef Minisat_GymSolver_h 28 | #define Minisat_GymSolver_h 29 | 30 | #include "minisat/simp/SimpSolver.h" 31 | #include "minisat/core/SolverTypes.h" 32 | 33 | namespace Minisat { 34 | 35 | class GymSolver { 36 | 37 | SimpSolver S; 38 | 39 | public: 40 | GymSolver(char*, bool, int); 41 | void step(int); 42 | double getReward(); 43 | bool getDone(); 44 | std::vector* getMetadata(); 45 | std::vector* getAssignments(); 46 | std::vector* getActivities(); 47 | std::vector >* getClauses(); 48 | }; 49 | 50 | } 51 | 52 | #endif -------------------------------------------------------------------------------- /minisat/minisat/gym/GymSolver.i: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /* 9 | This is the main interface for python to communicate with the solver. In the original implementation 10 | the state was turned into a string which was later parsed on the python side. 11 | We have rewritten this and return python lists instead. One step further would be to return numpy arrays, which 12 | should potentially be faster 13 | */ 14 | 15 | %module GymSolver 16 | 17 | %include 18 | // Graph-Q-SAT UPD: return vectors to support variable sized lists. The original version had a fixed sized arrays. 19 | %typemap(out) std::vector *getMetadata %{ 20 | $result = PyList_New($1->size()); 21 | for (int i = 0; i < $1->size(); ++i) { 22 | PyList_SetItem($result, i, PyLong_FromLong((*$1)[i])); 23 | } 24 | %} 25 | 26 | %typemap(out) std::vector *getAssignments %{ 27 | $result = PyList_New($1->size()); 28 | for (int i = 0; i < $1->size(); ++i) { 29 | PyList_SetItem($result, i, PyLong_FromLong((*$1)[i])); 30 | } 31 | %} 32 | 33 | %typemap(out) std::vector *getActivities %{ 34 | $result = PyList_New($1->size()); 35 | for (int i = 0; i < $1->size(); ++i) { 36 | PyList_SetItem($result, i, PyFloat_FromDouble((*$1)[i])); 37 | } 38 | %} 39 | 40 | %typemap(out) std::vector > *getClauses %{ 41 | $result = PyList_New($1->size()); 42 | for (int i = 0; i < $1->size(); ++i) { 43 | std::vector curr_clause_vec = (*$1)[i]; 44 | int clause_size = curr_clause_vec.size(); 45 | 46 | PyObject* curr_clause = PyList_New(clause_size); 47 | for (int j = 0; j < clause_size; ++j) { 48 | PyList_SetItem(curr_clause, j, PyLong_FromLong(curr_clause_vec[j])); 49 | } 50 | PyList_SetItem($result, i, curr_clause); 51 | } 52 | %} 53 | // end of Graph-Q-SAT UPD. 54 | %include "GymSolver.h" 55 | 56 | %{ 57 | #include 58 | #include "GymSolver.h" 59 | %} 60 | -------------------------------------------------------------------------------- /minisat/minisat/gym/GymSolver.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by SWIG (http://www.swig.org). 2 | # Version 3.0.12 3 | # 4 | # Do not make changes to this file unless you know what you are doing--modify 5 | # the SWIG interface file instead. 6 | 7 | from sys import version_info as _swig_python_version_info 8 | 9 | if _swig_python_version_info >= (2, 7, 0): 10 | 11 | def swig_import_helper(): 12 | import importlib 13 | 14 | pkg = __name__.rpartition(".")[0] 15 | mname = ".".join((pkg, "_GymSolver")).lstrip(".") 16 | try: 17 | return importlib.import_module(mname) 18 | except ImportError: 19 | return importlib.import_module("_GymSolver") 20 | 21 | _GymSolver = swig_import_helper() 22 | del swig_import_helper 23 | elif _swig_python_version_info >= (2, 6, 0): 24 | 25 | def swig_import_helper(): 26 | from os.path import dirname 27 | import imp 28 | 29 | fp = None 30 | try: 31 | fp, pathname, description = imp.find_module( 32 | "_GymSolver", [dirname(__file__)] 33 | ) 34 | except ImportError: 35 | import _GymSolver 36 | 37 | return _GymSolver 38 | try: 39 | _mod = imp.load_module("_GymSolver", fp, pathname, description) 40 | finally: 41 | if fp is not None: 42 | fp.close() 43 | return _mod 44 | 45 | _GymSolver = swig_import_helper() 46 | del swig_import_helper 47 | else: 48 | import _GymSolver 49 | del _swig_python_version_info 50 | 51 | try: 52 | _swig_property = property 53 | except NameError: 54 | pass # Python < 2.2 doesn't have 'property'. 55 | 56 | try: 57 | import builtins as __builtin__ 58 | except ImportError: 59 | import __builtin__ 60 | 61 | 62 | def _swig_setattr_nondynamic(self, class_type, name, value, static=1): 63 | if name == "thisown": 64 | return self.this.own(value) 65 | if name == "this": 66 | if type(value).__name__ == "SwigPyObject": 67 | self.__dict__[name] = value 68 | return 69 | method = class_type.__swig_setmethods__.get(name, None) 70 | if method: 71 | return method(self, value) 72 | if not static: 73 | if _newclass: 74 | object.__setattr__(self, name, value) 75 | else: 76 | self.__dict__[name] = value 77 | else: 78 | raise AttributeError("You cannot add attributes to %s" % self) 79 | 80 | 81 | def _swig_setattr(self, class_type, name, value): 82 | return _swig_setattr_nondynamic(self, class_type, name, value, 0) 83 | 84 | 85 | def _swig_getattr(self, class_type, name): 86 | if name == "thisown": 87 | return self.this.own() 88 | method = class_type.__swig_getmethods__.get(name, None) 89 | if method: 90 | return method(self) 91 | raise AttributeError( 92 | "'%s' object has no attribute '%s'" % (class_type.__name__, name) 93 | ) 94 | 95 | 96 | def _swig_repr(self): 97 | try: 98 | strthis = "proxy of " + self.this.__repr__() 99 | except __builtin__.Exception: 100 | strthis = "" 101 | return "<%s.%s; %s >" % ( 102 | self.__class__.__module__, 103 | self.__class__.__name__, 104 | strthis, 105 | ) 106 | 107 | 108 | try: 109 | _object = object 110 | _newclass = 1 111 | except __builtin__.Exception: 112 | 113 | class _object: 114 | pass 115 | 116 | _newclass = 0 117 | 118 | 119 | class GymSolver(_object): 120 | __swig_setmethods__ = {} 121 | __setattr__ = lambda self, name, value: _swig_setattr(self, GymSolver, name, value) 122 | __swig_getmethods__ = {} 123 | __getattr__ = lambda self, name: _swig_getattr(self, GymSolver, name) 124 | __repr__ = _swig_repr 125 | 126 | def __init__(self, arg2, arg3, arg4): 127 | this = _GymSolver.new_GymSolver(arg2, arg3, arg4) 128 | try: 129 | self.this.append(this) 130 | except __builtin__.Exception: 131 | self.this = this 132 | 133 | def step(self, arg2): 134 | return _GymSolver.GymSolver_step(self, arg2) 135 | 136 | def getReward(self): 137 | return _GymSolver.GymSolver_getReward(self) 138 | 139 | def getDone(self): 140 | return _GymSolver.GymSolver_getDone(self) 141 | 142 | def getMetadata(self): 143 | return _GymSolver.GymSolver_getMetadata(self) 144 | 145 | def getAssignments(self): 146 | return _GymSolver.GymSolver_getAssignments(self) 147 | 148 | def getActivities(self): 149 | return _GymSolver.GymSolver_getActivities(self) 150 | 151 | def getClauses(self): 152 | return _GymSolver.GymSolver_getClauses(self) 153 | 154 | __swig_destroy__ = _GymSolver.delete_GymSolver 155 | __del__ = lambda self: None 156 | 157 | 158 | GymSolver_swigregister = _GymSolver.GymSolver_swigregister 159 | GymSolver_swigregister(GymSolver) 160 | 161 | # This file is compatible with both classic and new-style classes. 162 | -------------------------------------------------------------------------------- /minisat/minisat/gym/GymSolver_wrap.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/GraphQSat/cfc8f3860469e1b0a2b6a85f39c6f9ba5fc905d0/minisat/minisat/gym/GymSolver_wrap.o -------------------------------------------------------------------------------- /minisat/minisat/gym/MiniSATEnv.py: -------------------------------------------------------------------------------- 1 | ################################################################################################################################# 2 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 3 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 4 | ################################################################################################################################# 5 | # MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 6 | # Copyright (c) 2007-2010 Niklas Sorensson 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a 9 | # copy of this software and associated documentation files (the 10 | # "Software"), to deal in the Software without restriction, including 11 | # without limitation the rights to use, copy, modify, merge, publish, 12 | # distribute, sublicense, and/or sell copies of the Software, and to 13 | # permit persons to whom the Software is furnished to do so, subject to 14 | # the following conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included 17 | # in all copies or substantial portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 | # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 23 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | # 27 | 28 | # Graph-Q-SAT-UPD. This file is heavly changed and supports variable-sized SAT problems, multiple datasets 29 | # and generates graph-state representations for Graph-Q-SAT. 30 | 31 | import numpy as np 32 | import gym 33 | import random 34 | from os import listdir 35 | from os.path import join, realpath, split 36 | from .GymSolver import GymSolver 37 | import sys 38 | 39 | MINISAT_DECISION_CONSTANT = 32767 40 | VAR_ID_IDX = ( 41 | 0 # put 1 at the position of this index to indicate that the node is a variable 42 | ) 43 | 44 | 45 | class gym_sat_Env(gym.Env): 46 | def __init__( 47 | self, 48 | problems_paths, 49 | args, 50 | test_mode=False, 51 | max_cap_fill_buffer=True, 52 | penalty_size=None, 53 | with_restarts=None, 54 | compare_with_restarts=None, 55 | max_data_limit_per_set=None, 56 | ): 57 | 58 | self.problems_paths = [realpath(el) for el in problems_paths.split(":")] 59 | self.args = args 60 | self.test_mode = test_mode 61 | 62 | self.max_data_limit_per_set = max_data_limit_per_set 63 | pre_test_files = [ 64 | [join(dir, f) for f in listdir(dir) if f.endswith(".cnf")] 65 | for dir in self.problems_paths 66 | ] 67 | if self.max_data_limit_per_set is not None: 68 | pre_test_files = [ 69 | np.random.choice(el, size=max_data_limit_per_set, replace=False) 70 | for el in pre_test_files 71 | ] 72 | self.test_files = [sl for el in pre_test_files for sl in el] 73 | 74 | self.metadata = {} 75 | self.max_decisions_cap = float("inf") 76 | self.max_cap_fill_buffer = max_cap_fill_buffer 77 | self.penalty_size = penalty_size if penalty_size is not None else 0.0001 78 | self.with_restarts = True if with_restarts is None else with_restarts 79 | self.compare_with_restarts = ( 80 | False if compare_with_restarts is None else compare_with_restarts 81 | ) 82 | 83 | try: 84 | for dir in self.problems_paths: 85 | self.metadata[dir] = {} 86 | with open(join(dir, "METADATA")) as f: 87 | for l in f: 88 | k, rscore, msscore = l.split(",") 89 | self.metadata[dir][k] = [int(rscore), int(msscore)] 90 | except Exception as e: 91 | print(e) 92 | print("No metadata available, that is fine for metadata generator.") 93 | self.metadata = None 94 | self.test_file_num = len(self.test_files) 95 | self.test_to = 0 96 | 97 | self.step_ctr = 0 98 | self.curr_problem = None 99 | 100 | self.global_in_size = 1 101 | self.vertex_in_size = 2 102 | self.edge_in_size = 2 103 | self.max_clause_len = 0 104 | 105 | def parse_state_as_graph(self): 106 | 107 | # if S is already Done, should return a dummy state to store in the buffer. 108 | if self.S.getDone(): 109 | # to not mess with the c++ code, let's build a dummy graph which will not be used in the q updates anyways 110 | # since we multiply (1-dones) 111 | empty_state = self.get_dummy_state() 112 | self.decision_to_var_mapping = { 113 | el: el 114 | for sl in range(empty_state[0].shape[0]) 115 | for el in (2 * sl, 2 * sl + 1) 116 | } 117 | return empty_state, True 118 | 119 | # S is not yet Done, parse and return real state 120 | 121 | ( 122 | total_var, 123 | _, 124 | current_depth, 125 | n_init_clauses, 126 | num_restarts, 127 | _, 128 | ) = self.S.getMetadata() 129 | var_assignments = self.S.getAssignments() 130 | num_var = sum([1 for el in var_assignments if el == 2]) 131 | 132 | # only valid decisions 133 | valid_decisions = [ 134 | el 135 | for i in range(len(var_assignments)) 136 | for el in (2 * i, 2 * i + 1) 137 | if var_assignments[i] == 2 138 | ] 139 | valid_vars = [ 140 | idx for idx in range(len(var_assignments)) if var_assignments[idx] == 2 141 | ] 142 | # we need remapping since we keep only unassigned vars in the observations, 143 | # however, the environment does know about this, it expects proper indices of the variables 144 | vars_remapping = {el: i for i, el in enumerate(valid_vars)} 145 | self.decision_to_var_mapping = { 146 | i: val_decision for i, val_decision in enumerate(valid_decisions) 147 | } 148 | 149 | # we should return the vertex/edge numpy objects from the c++ code to make this faster 150 | clauses = self.S.getClauses() 151 | 152 | if len(clauses) == 0: 153 | # this is to avoid feeding empty data structures to our model 154 | # when the MiniSAT environment returns an empty graph 155 | # it might return an empty graph since we do not construct it when 156 | # step > max_cap and max_cap can be zero (all decisions are made by MiniSAT's VSIDS). 157 | empty_state = self.get_dummy_state() 158 | self.decision_to_var_mapping = { 159 | el: el 160 | for sl in range(empty_state[0].shape[0]) 161 | for el in (2 * sl, 2 * sl + 1) 162 | } 163 | return empty_state, False 164 | 165 | clause_counter = 0 166 | clauses_lens = [len(cl) for cl in clauses] 167 | self.max_clause_len = max(clauses_lens) 168 | edge_data = np.zeros((sum(clauses_lens) * 2, 2), dtype=np.float32) 169 | connectivity = np.zeros((2, edge_data.shape[0]), dtype=np.int) 170 | ec = 0 171 | for cl in clauses: 172 | for l in cl: 173 | # if positive, create a [0,1] edge from the var to the current clause, else [1,0] 174 | # data = [1, 0] if l==True else [0, 1] 175 | 176 | # this is not a typo, we want two edge here 177 | edge_data[ec : ec + 2, int(l > 0)] = 1 178 | 179 | remapped_l = vars_remapping[abs(l) - 1] 180 | # from var to clause 181 | connectivity[0, ec] = remapped_l 182 | connectivity[1, ec] = num_var + clause_counter 183 | # from clause to var 184 | connectivity[0, ec + 1] = num_var + clause_counter 185 | connectivity[1, ec + 1] = remapped_l 186 | 187 | ec += 2 188 | clause_counter += 1 189 | 190 | vertex_data = np.zeros( 191 | (num_var + clause_counter, self.vertex_in_size), dtype=np.float32 192 | ) # both vars and clauses are vertex in the graph 193 | vertex_data[:num_var, VAR_ID_IDX] = 1 194 | vertex_data[num_var:, VAR_ID_IDX + 1] = 1 195 | 196 | return ( 197 | ( 198 | vertex_data, 199 | edge_data, 200 | connectivity, 201 | np.zeros((1, self.global_in_size), dtype=np.float32), 202 | ), 203 | False, 204 | ) 205 | 206 | def random_pick_satProb(self): 207 | if self.test_mode: # in the test mode, just iterate all test files in order 208 | filename = self.test_files[self.test_to] 209 | self.test_to += 1 210 | if self.test_to >= self.test_file_num: 211 | self.test_to = 0 212 | return filename 213 | else: # not in test mode, return a random file in "uf20-91" folder. 214 | return self.test_files[random.randint(0, self.test_file_num - 1)] 215 | 216 | def reset(self, max_decisions_cap=None): 217 | self.step_ctr = 0 218 | 219 | if max_decisions_cap is None: 220 | max_decisions_cap = sys.maxsize 221 | self.max_decisions_cap = max_decisions_cap 222 | self.curr_problem = self.random_pick_satProb() 223 | self.S = GymSolver(self.curr_problem, self.with_restarts, max_decisions_cap) 224 | self.max_clause_len = 0 225 | 226 | self.curr_state, self.isSolved = self.parse_state_as_graph() 227 | return self.curr_state 228 | 229 | def step(self, decision, dummy=False): 230 | # now when we drop variables, we store the mapping 231 | # convert dropped var decision to the original decision id 232 | if decision >= 0: 233 | decision = self.decision_to_var_mapping[decision] 234 | self.step_ctr += 1 235 | 236 | if dummy: 237 | self.S.step(MINISAT_DECISION_CONSTANT) 238 | ( 239 | num_var, 240 | _, 241 | current_depth, 242 | n_init_clauses, 243 | num_restarts, 244 | _, 245 | ) = self.S.getMetadata() 246 | return ( 247 | None, 248 | None, 249 | self.S.getDone(), 250 | { 251 | "curr_problem": self.curr_problem, 252 | "num_restarts": num_restarts, 253 | "max_clause_len": self.max_clause_len, 254 | }, 255 | ) 256 | 257 | if self.step_ctr > self.max_decisions_cap: 258 | while not self.S.getDone(): 259 | self.S.step(MINISAT_DECISION_CONSTANT) 260 | if self.max_cap_fill_buffer: 261 | # return every next state when param is true 262 | break 263 | self.step_ctr += 1 264 | else: 265 | # if we are here, we are not filling the buffer and we need to reduce the counter by one to 266 | # correct for the increment for the last state 267 | self.step_ctr -= 1 268 | else: 269 | # TODO for debugging purposes, we need to add all the checks 270 | # I removed this action_set checks for performance optimisation 271 | 272 | # var_values = self.curr_state[0][:, 2] 273 | # var_values = self.S.getAssignments() 274 | # action_set = [ 275 | # a 276 | # for v_idx, v in enumerate(var_values) 277 | # for a in (v_idx * 2, v_idx * 2 + 1) 278 | # if v == 2 279 | # ] 280 | 281 | if decision < 0: # this is to say that let minisat pick the decision 282 | decision = MINISAT_DECISION_CONSTANT 283 | elif ( 284 | decision % 2 == 0 285 | ): # this is to say that pick decision and assign positive value 286 | decision = int(decision / 2 + 1) 287 | else: # this is to say that pick decision and assign negative value 288 | decision = 0 - int(decision / 2 + 1) 289 | 290 | # if (decision == MINISAT_DECISION_CONSTANT) or orig_decision in action_set: 291 | self.S.step(decision) 292 | # else: 293 | # raise ValueError("Illegal action") 294 | 295 | self.curr_state, self.isSolved = self.parse_state_as_graph() 296 | ( 297 | num_var, 298 | _, 299 | current_depth, 300 | n_init_clauses, 301 | num_restarts, 302 | _, 303 | ) = self.S.getMetadata() 304 | 305 | # if we fill the buffer, the rewards are the same as GQSAT was making decisions 306 | if self.step_ctr > self.max_decisions_cap and not self.max_cap_fill_buffer: 307 | # if we do not fill the buffer, but play till the end, we still need to penalize 308 | # since GQSAT hasn't solved the problem 309 | step_reward = -self.penalty_size 310 | else: 311 | step_reward = 0 if self.isSolved else -self.penalty_size 312 | 313 | return ( 314 | self.curr_state, 315 | step_reward, 316 | self.isSolved, 317 | { 318 | "curr_problem": self.curr_problem, 319 | "num_restarts": num_restarts, 320 | "max_clause_len": self.max_clause_len, 321 | }, 322 | ) 323 | 324 | def normalized_score(self, steps, problem): 325 | pdir, pname = split(problem) 326 | no_restart_steps, restart_steps = self.metadata[pdir][pname] 327 | if self.compare_with_restarts: 328 | return restart_steps / steps 329 | else: 330 | return no_restart_steps / steps 331 | 332 | def get_dummy_state(self): 333 | DUMMY_V = np.zeros((2, self.vertex_in_size), dtype=np.float32) 334 | DUMMY_V[:, VAR_ID_IDX] = 1 335 | DUMMY_STATE = ( 336 | DUMMY_V, 337 | np.zeros((2, self.edge_in_size), dtype=np.float32), 338 | np.eye(2, dtype=np.long), 339 | np.zeros((1, self.global_in_size), dtype=np.float32), 340 | ) 341 | return ( 342 | DUMMY_STATE[0], 343 | DUMMY_STATE[1], 344 | DUMMY_STATE[2], 345 | np.zeros((1, self.global_in_size), dtype=np.float32), 346 | ) 347 | -------------------------------------------------------------------------------- /minisat/minisat/gym/_GymSolver.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NVIDIA/GraphQSat/cfc8f3860469e1b0a2b6a85f39c6f9ba5fc905d0/minisat/minisat/gym/_GymSolver.so -------------------------------------------------------------------------------- /minisat/minisat/mtl/Alg.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*******************************************************************************************[Alg.h] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_Alg_h 29 | #define Minisat_Alg_h 30 | 31 | #include "minisat/mtl/Vec.h" 32 | 33 | namespace Minisat { 34 | 35 | //================================================================================================= 36 | // Useful functions on vector-like types: 37 | 38 | //================================================================================================= 39 | // Removing and searching for elements: 40 | // 41 | 42 | template 43 | static inline void remove(V& ts, const T& t) 44 | { 45 | int j = 0; 46 | for (; j < (int)ts.size() && ts[j] != t; j++); 47 | assert(j < (int)ts.size()); 48 | for (; j < (int)ts.size()-1; j++) ts[j] = ts[j+1]; 49 | ts.pop(); 50 | } 51 | 52 | 53 | template 54 | static inline bool find(V& ts, const T& t) 55 | { 56 | int j = 0; 57 | for (; j < (int)ts.size() && ts[j] != t; j++); 58 | return j < (int)ts.size(); 59 | } 60 | 61 | 62 | //================================================================================================= 63 | // Copying vectors with support for nested vector types: 64 | // 65 | 66 | // Base case: 67 | template 68 | static inline void copy(const T& from, T& to) 69 | { 70 | to = from; 71 | } 72 | 73 | // Recursive case: 74 | template 75 | static inline void copy(const vec& from, vec& to, bool append = false) 76 | { 77 | if (!append) 78 | to.clear(); 79 | for (int i = 0; i < from.size(); i++){ 80 | to.push(); 81 | copy(from[i], to.last()); 82 | } 83 | } 84 | 85 | template 86 | static inline void append(const vec& from, vec& to){ copy(from, to, true); } 87 | 88 | //================================================================================================= 89 | } 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*****************************************************************************************[Alloc.h] 9 | Copyright (c) 2008-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | 28 | #ifndef Minisat_Alloc_h 29 | #define Minisat_Alloc_h 30 | 31 | #include "minisat/mtl/XAlloc.h" 32 | #include "minisat/mtl/Vec.h" 33 | 34 | namespace Minisat { 35 | 36 | //================================================================================================= 37 | // Simple Region-based memory allocator: 38 | 39 | template 40 | class RegionAllocator 41 | { 42 | T* memory; 43 | uint32_t sz; 44 | uint32_t cap; 45 | uint32_t wasted_; 46 | 47 | void capacity(uint32_t min_cap); 48 | 49 | public: 50 | // TODO: make this a class for better type-checking? 51 | typedef uint32_t Ref; 52 | enum { Ref_Undef = UINT32_MAX }; 53 | enum { Unit_Size = sizeof(T) }; 54 | 55 | explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); } 56 | ~RegionAllocator() 57 | { 58 | if (memory != NULL) 59 | ::free(memory); 60 | } 61 | 62 | 63 | uint32_t size () const { return sz; } 64 | uint32_t wasted () const { return wasted_; } 65 | 66 | Ref alloc (int size); 67 | void free (int size) { wasted_ += size; } 68 | 69 | // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): 70 | T& operator[](Ref r) { assert(r < sz); return memory[r]; } 71 | const T& operator[](Ref r) const { assert(r < sz); return memory[r]; } 72 | 73 | T* lea (Ref r) { assert(r < sz); return &memory[r]; } 74 | const T* lea (Ref r) const { assert(r < sz); return &memory[r]; } 75 | Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]); 76 | return (Ref)(t - &memory[0]); } 77 | 78 | void moveTo(RegionAllocator& to) { 79 | if (to.memory != NULL) ::free(to.memory); 80 | to.memory = memory; 81 | to.sz = sz; 82 | to.cap = cap; 83 | to.wasted_ = wasted_; 84 | 85 | memory = NULL; 86 | sz = cap = wasted_ = 0; 87 | } 88 | 89 | 90 | }; 91 | 92 | template 93 | void RegionAllocator::capacity(uint32_t min_cap) 94 | { 95 | if (cap >= min_cap) return; 96 | 97 | uint32_t prev_cap = cap; 98 | while (cap < min_cap){ 99 | // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the 100 | // result even by clearing the least significant bit. The resulting sequence of capacities 101 | // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when 102 | // using 'uint32_t' as indices so that as much as possible of this space can be used. 103 | uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1; 104 | cap += delta; 105 | 106 | if (cap <= prev_cap) 107 | throw OutOfMemoryException(); 108 | } 109 | // printf(" .. (%p) cap = %u\n", this, cap); 110 | 111 | assert(cap > 0); 112 | memory = (T*)xrealloc(memory, sizeof(T)*cap); 113 | } 114 | 115 | 116 | template 117 | typename RegionAllocator::Ref 118 | RegionAllocator::alloc(int size) 119 | { 120 | // printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout); 121 | assert(size > 0); 122 | capacity(sz + size); 123 | 124 | uint32_t prev_sz = sz; 125 | sz += size; 126 | 127 | // Handle overflow: 128 | if (sz < prev_sz) 129 | throw OutOfMemoryException(); 130 | 131 | return prev_sz; 132 | } 133 | 134 | 135 | //================================================================================================= 136 | } 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Heap.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /******************************************************************************************[Heap.h] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_Heap_h 29 | #define Minisat_Heap_h 30 | 31 | #include "minisat/mtl/Vec.h" 32 | #include "minisat/mtl/IntMap.h" 33 | 34 | namespace Minisat { 35 | 36 | //================================================================================================= 37 | // A heap implementation with support for decrease/increase key. 38 | 39 | 40 | template > 41 | class Heap { 42 | vec heap; // Heap of Keys 43 | IntMap indices; // Each Key's position (index) in the Heap 44 | Comp lt; // The heap is a minimum-heap with respect to this comparator 45 | 46 | // Index "traversal" functions 47 | static inline int left (int i) { return i*2+1; } 48 | static inline int right (int i) { return (i+1)*2; } 49 | static inline int parent(int i) { return (i-1) >> 1; } 50 | 51 | 52 | void percolateUp(int i) 53 | { 54 | K x = heap[i]; 55 | int p = parent(i); 56 | 57 | while (i != 0 && lt(x, heap[p])){ 58 | heap[i] = heap[p]; 59 | indices[heap[p]] = i; 60 | i = p; 61 | p = parent(p); 62 | } 63 | heap [i] = x; 64 | indices[x] = i; 65 | } 66 | 67 | 68 | void percolateDown(int i) 69 | { 70 | K x = heap[i]; 71 | while (left(i) < heap.size()){ 72 | int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); 73 | if (!lt(heap[child], x)) break; 74 | heap[i] = heap[child]; 75 | indices[heap[i]] = i; 76 | i = child; 77 | } 78 | heap [i] = x; 79 | indices[x] = i; 80 | } 81 | 82 | 83 | public: 84 | Heap(const Comp& c, MkIndex _index = MkIndex()) : indices(_index), lt(c) {} 85 | 86 | int size () const { return heap.size(); } 87 | bool empty () const { return heap.size() == 0; } 88 | bool inHeap (K k) const { return indices.has(k) && indices[k] >= 0; } 89 | int operator[](int index) const { assert(index < heap.size()); return heap[index]; } 90 | 91 | void decrease (K k) { assert(inHeap(k)); percolateUp (indices[k]); } 92 | void increase (K k) { assert(inHeap(k)); percolateDown(indices[k]); } 93 | 94 | 95 | // Safe variant of insert/decrease/increase: 96 | void update(K k) 97 | { 98 | if (!inHeap(k)) 99 | insert(k); 100 | else { 101 | percolateUp(indices[k]); 102 | percolateDown(indices[k]); } 103 | } 104 | 105 | 106 | void insert(K k) 107 | { 108 | indices.reserve(k, -1); 109 | assert(!inHeap(k)); 110 | 111 | indices[k] = heap.size(); 112 | heap.push(k); 113 | percolateUp(indices[k]); 114 | } 115 | 116 | 117 | void remove(K k) 118 | { 119 | assert(inHeap(k)); 120 | 121 | int k_pos = indices[k]; 122 | indices[k] = -1; 123 | 124 | if (k_pos < heap.size()-1){ 125 | heap[k_pos] = heap.last(); 126 | indices[heap[k_pos]] = k_pos; 127 | heap.pop(); 128 | percolateDown(k_pos); 129 | }else 130 | heap.pop(); 131 | } 132 | 133 | 134 | K removeMin() 135 | { 136 | K x = heap[0]; 137 | heap[0] = heap.last(); 138 | indices[heap[0]] = 0; 139 | indices[x] = -1; 140 | heap.pop(); 141 | if (heap.size() > 1) percolateDown(0); 142 | return x; 143 | } 144 | 145 | 146 | // Rebuild the heap from scratch, using the elements in 'ns': 147 | void build(const vec& ns) { 148 | for (int i = 0; i < heap.size(); i++) 149 | indices[heap[i]] = -1; 150 | heap.clear(); 151 | 152 | for (int i = 0; i < ns.size(); i++){ 153 | // TODO: this should probably call reserve instead of relying on it being reserved already. 154 | assert(indices.has(ns[i])); 155 | indices[ns[i]] = i; 156 | heap.push(ns[i]); } 157 | 158 | for (int i = heap.size() / 2 - 1; i >= 0; i--) 159 | percolateDown(i); 160 | } 161 | 162 | void clear(bool dispose = false) 163 | { 164 | // TODO: shouldn't the 'indices' map also be dispose-cleared? 165 | for (int i = 0; i < heap.size(); i++) 166 | indices[heap[i]] = -1; 167 | heap.clear(dispose); 168 | } 169 | }; 170 | 171 | 172 | //================================================================================================= 173 | } 174 | 175 | #endif 176 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/IntMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /****************************************************************************************[IntMap.h] 9 | Copyright (c) 2011, Niklas Sorensson 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 11 | associated documentation files (the "Software"), to deal in the Software without restriction, 12 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 13 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or 17 | substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 20 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 23 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | **************************************************************************************************/ 25 | 26 | #ifndef Minisat_IntMap_h 27 | #define Minisat_IntMap_h 28 | 29 | #include "minisat/mtl/Vec.h" 30 | 31 | namespace Minisat { 32 | 33 | template struct MkIndexDefault { 34 | typename vec::Size operator()(T t) const { return (typename vec::Size)t; } 35 | }; 36 | 37 | template > 38 | class IntMap { 39 | vec map; 40 | MkIndex index; 41 | public: 42 | explicit IntMap(MkIndex _index = MkIndex()) : index(_index){} 43 | 44 | bool has (K k) const { return index(k) < map.size(); } 45 | 46 | const V& operator[](K k) const { assert(has(k)); return map[index(k)]; } 47 | V& operator[](K k) { assert(has(k)); return map[index(k)]; } 48 | 49 | const V* begin () const { return &map[0]; } 50 | const V* end () const { return &map[map.size()]; } 51 | V* begin () { return &map[0]; } 52 | V* end () { return &map[map.size()]; } 53 | 54 | const int size() {return map.size();} 55 | 56 | void reserve(K key, V pad) { map.growTo(index(key)+1, pad); } 57 | void reserve(K key) { map.growTo(index(key)+1); } 58 | void insert (K key, V val, V pad){ reserve(key, pad); operator[](key) = val; } 59 | void insert (K key, V val) { reserve(key); operator[](key) = val; } 60 | 61 | void clear (bool dispose = false) { map.clear(dispose); } 62 | void moveTo (IntMap& to) { map.moveTo(to.map); to.index = index; } 63 | void copyTo (IntMap& to) const { map.copyTo(to.map); to.index = index; } 64 | }; 65 | 66 | 67 | template > 68 | class IntSet 69 | { 70 | IntMap in_set; 71 | vec xs; 72 | 73 | public: 74 | // Size operations: 75 | int size (void) const { return xs.size(); } 76 | void clear (bool free = false){ 77 | if (free) 78 | in_set.clear(true); 79 | else 80 | for (int i = 0; i < xs.size(); i++) 81 | in_set[xs[i]] = 0; 82 | xs.clear(free); 83 | } 84 | 85 | // Allow inspecting the internal vector: 86 | const vec& 87 | toVec () const { return xs; } 88 | 89 | // Vector interface: 90 | K operator [] (int index) const { return xs[index]; } 91 | 92 | 93 | void insert (K k) { in_set.reserve(k, 0); if (!in_set[k]) { in_set[k] = 1; xs.push(k); } } 94 | bool has (K k) { in_set.reserve(k, 0); return in_set[k]; } 95 | }; 96 | 97 | #if 0 98 | template > 99 | class IntMapNil { 100 | vec map; 101 | V nil; 102 | 103 | public: 104 | IntMap(){} 105 | 106 | void reserve(K); 107 | V& find (K); 108 | const V& operator[](K k) const; 109 | 110 | }; 111 | #endif 112 | 113 | //================================================================================================= 114 | } // namespace Minisat 115 | #endif 116 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/IntTypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /**************************************************************************************[IntTypes.h] 9 | Copyright (c) 2009-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | #ifndef Minisat_IntTypes_h 28 | #define Minisat_IntTypes_h 29 | 30 | #ifdef __sun 31 | // Not sure if there are newer versions that support C99 headers. The 32 | // needed features are implemented in the headers below though: 33 | 34 | # include 35 | # include 36 | # include 37 | 38 | #else 39 | 40 | # include 41 | # include 42 | 43 | #endif 44 | 45 | #include 46 | 47 | //================================================================================================= 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Map.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*******************************************************************************************[Map.h] 9 | Copyright (c) 2006-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | #ifndef Minisat_Map_h 28 | #define Minisat_Map_h 29 | 30 | #include "minisat/mtl/IntTypes.h" 31 | #include "minisat/mtl/Vec.h" 32 | 33 | namespace Minisat { 34 | 35 | //================================================================================================= 36 | // Default hash/equals functions 37 | // 38 | 39 | template struct Hash { uint32_t operator()(const K& k) const { return hash(k); } }; 40 | template struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } }; 41 | 42 | template struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } }; 43 | template struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } }; 44 | 45 | static inline uint32_t hash(uint32_t x){ return x; } 46 | static inline uint32_t hash(uint64_t x){ return (uint32_t)x; } 47 | static inline uint32_t hash(int32_t x) { return (uint32_t)x; } 48 | static inline uint32_t hash(int64_t x) { return (uint32_t)x; } 49 | 50 | 51 | //================================================================================================= 52 | // Some primes 53 | // 54 | 55 | static const int nprimes = 25; 56 | static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 }; 57 | 58 | //================================================================================================= 59 | // Hash table implementation of Maps 60 | // 61 | 62 | template, class E = Equal > 63 | class Map { 64 | public: 65 | struct Pair { K key; D data; }; 66 | 67 | private: 68 | H hash; 69 | E equals; 70 | 71 | vec* table; 72 | int cap; 73 | int size; 74 | 75 | // Don't allow copying (error prone): 76 | Map& operator = (Map& other); 77 | Map (Map& other); 78 | 79 | bool checkCap(int new_size) const { return new_size > cap; } 80 | 81 | int32_t index (const K& k) const { return hash(k) % cap; } 82 | void _insert (const K& k, const D& d) { 83 | vec& ps = table[index(k)]; 84 | ps.push(); ps.last().key = k; ps.last().data = d; } 85 | 86 | void rehash () { 87 | const vec* old = table; 88 | 89 | int old_cap = cap; 90 | int newsize = primes[0]; 91 | for (int i = 1; newsize <= cap && i < nprimes; i++) 92 | newsize = primes[i]; 93 | 94 | table = new vec[newsize]; 95 | cap = newsize; 96 | 97 | for (int i = 0; i < old_cap; i++){ 98 | for (int j = 0; j < old[i].size(); j++){ 99 | _insert(old[i][j].key, old[i][j].data); }} 100 | 101 | delete [] old; 102 | 103 | // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize); 104 | } 105 | 106 | 107 | public: 108 | 109 | Map () : table(NULL), cap(0), size(0) {} 110 | Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){} 111 | ~Map () { delete [] table; } 112 | 113 | // PRECONDITION: the key must already exist in the map. 114 | const D& operator [] (const K& k) const 115 | { 116 | assert(size != 0); 117 | const D* res = NULL; 118 | const vec& ps = table[index(k)]; 119 | for (int i = 0; i < ps.size(); i++) 120 | if (equals(ps[i].key, k)) 121 | res = &ps[i].data; 122 | assert(res != NULL); 123 | return *res; 124 | } 125 | 126 | // PRECONDITION: the key must already exist in the map. 127 | D& operator [] (const K& k) 128 | { 129 | assert(size != 0); 130 | D* res = NULL; 131 | vec& ps = table[index(k)]; 132 | for (int i = 0; i < ps.size(); i++) 133 | if (equals(ps[i].key, k)) 134 | res = &ps[i].data; 135 | assert(res != NULL); 136 | return *res; 137 | } 138 | 139 | // PRECONDITION: the key must *NOT* exist in the map. 140 | void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; } 141 | bool peek (const K& k, D& d) const { 142 | if (size == 0) return false; 143 | const vec& ps = table[index(k)]; 144 | for (int i = 0; i < ps.size(); i++) 145 | if (equals(ps[i].key, k)){ 146 | d = ps[i].data; 147 | return true; } 148 | return false; 149 | } 150 | 151 | bool has (const K& k) const { 152 | if (size == 0) return false; 153 | const vec& ps = table[index(k)]; 154 | for (int i = 0; i < ps.size(); i++) 155 | if (equals(ps[i].key, k)) 156 | return true; 157 | return false; 158 | } 159 | 160 | // PRECONDITION: the key must exist in the map. 161 | void remove(const K& k) { 162 | assert(table != NULL); 163 | vec& ps = table[index(k)]; 164 | int j = 0; 165 | for (; j < ps.size() && !equals(ps[j].key, k); j++); 166 | assert(j < ps.size()); 167 | ps[j] = ps.last(); 168 | ps.pop(); 169 | size--; 170 | } 171 | 172 | void clear () { 173 | cap = size = 0; 174 | delete [] table; 175 | table = NULL; 176 | } 177 | 178 | int elems() const { return size; } 179 | int bucket_count() const { return cap; } 180 | 181 | // NOTE: the hash and equality objects are not moved by this method: 182 | void moveTo(Map& other){ 183 | delete [] other.table; 184 | 185 | other.table = table; 186 | other.cap = cap; 187 | other.size = size; 188 | 189 | table = NULL; 190 | size = cap = 0; 191 | } 192 | 193 | // NOTE: given a bit more time, I could make a more C++-style iterator out of this: 194 | const vec& bucket(int i) const { return table[i]; } 195 | }; 196 | 197 | //================================================================================================= 198 | } 199 | 200 | #endif 201 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*****************************************************************************************[Queue.h] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_Queue_h 29 | #define Minisat_Queue_h 30 | 31 | #include "minisat/mtl/Vec.h" 32 | 33 | namespace Minisat { 34 | 35 | //================================================================================================= 36 | 37 | template 38 | class Queue { 39 | vec buf; 40 | int first; 41 | int end; 42 | 43 | public: 44 | typedef T Key; 45 | 46 | Queue() : buf(1), first(0), end(0) {} 47 | 48 | void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; } 49 | int size () const { return (end >= first) ? end - first : end - first + buf.size(); } 50 | 51 | const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 52 | T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 53 | 54 | T peek () const { assert(first != end); return buf[first]; } 55 | void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; } 56 | void insert(T elem) { // INVARIANT: buf[end] is always unused 57 | buf[end++] = elem; 58 | if (end == buf.size()) end = 0; 59 | if (first == end){ // Resize: 60 | vec tmp((buf.size()*3 + 1) >> 1); 61 | //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0); 62 | int i = 0; 63 | for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j]; 64 | for (int j = 0 ; j < end ; j++) tmp[i++] = buf[j]; 65 | first = 0; 66 | end = buf.size(); 67 | tmp.moveTo(buf); 68 | } 69 | } 70 | }; 71 | 72 | 73 | //================================================================================================= 74 | } 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Rnd.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*******************************************************************************************[Rnd.h] 9 | Copyright (c) 2012, Niklas Sorensson 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 11 | associated documentation files (the "Software"), to deal in the Software without restriction, 12 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 13 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or 17 | substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 20 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 23 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | **************************************************************************************************/ 25 | 26 | #ifndef Minisat_Rnd_h 27 | #define Minisat_Rnd_h 28 | 29 | #include "minisat/mtl/Vec.h" 30 | 31 | namespace Minisat { 32 | 33 | // Generate a random double: 34 | static inline double drand(double& seed) 35 | { 36 | seed *= 1389796; 37 | int q = (int)(seed / 2147483647); 38 | seed -= (double)q * 2147483647; 39 | return seed / 2147483647; 40 | } 41 | 42 | 43 | // Generate a random integer: 44 | static inline int irand(double& seed, int size) { return (int)(drand(seed) * size); } 45 | 46 | 47 | // Randomly shuffle the contents of a vector: 48 | template 49 | static void randomShuffle(double& seed, vec& xs) 50 | { 51 | for (int i = 0; i < xs.size(); i++){ 52 | int pick = i + irand(seed, xs.size() - i); 53 | T tmp = xs[i]; 54 | xs[i] = xs[pick]; 55 | xs[pick] = tmp; 56 | } 57 | } 58 | 59 | // Randomly shuffle a vector of a vector (ugly) 60 | template 61 | static void randomShuffle(double& seed, vec >& xs) 62 | { 63 | for (int i = 0; i < xs.size(); i++){ 64 | int pick = i + irand(seed, xs.size() - i); 65 | vec tmp; xs[i].moveTo(tmp); 66 | xs[pick].moveTo(xs[i]); 67 | tmp.moveTo(xs[pick]); 68 | } 69 | } 70 | 71 | 72 | //================================================================================================= 73 | } // namespace Minisat 74 | #endif 75 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Sort.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /******************************************************************************************[Sort.h] 9 | Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_Sort_h 29 | #define Minisat_Sort_h 30 | 31 | #include "minisat/mtl/Vec.h" 32 | 33 | //================================================================================================= 34 | // Some sorting algorithms for vec's 35 | 36 | 37 | namespace Minisat { 38 | 39 | template 40 | struct LessThan_default { 41 | bool operator () (T x, T y) { return x < y; } 42 | }; 43 | 44 | 45 | template 46 | void selectionSort(T* array, int size, LessThan lt) 47 | { 48 | int i, j, best_i; 49 | T tmp; 50 | 51 | for (i = 0; i < size-1; i++){ 52 | best_i = i; 53 | for (j = i+1; j < size; j++){ 54 | if (lt(array[j], array[best_i])) 55 | best_i = j; 56 | } 57 | tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; 58 | } 59 | } 60 | template static inline void selectionSort(T* array, int size) { 61 | selectionSort(array, size, LessThan_default()); } 62 | 63 | template 64 | void sort(T* array, int size, LessThan lt) 65 | { 66 | if (size <= 15) 67 | selectionSort(array, size, lt); 68 | 69 | else{ 70 | T pivot = array[size / 2]; 71 | T tmp; 72 | int i = -1; 73 | int j = size; 74 | 75 | for(;;){ 76 | do i++; while(lt(array[i], pivot)); 77 | do j--; while(lt(pivot, array[j])); 78 | 79 | if (i >= j) break; 80 | 81 | tmp = array[i]; array[i] = array[j]; array[j] = tmp; 82 | } 83 | 84 | sort(array , i , lt); 85 | sort(&array[i], size-i, lt); 86 | } 87 | } 88 | template static inline void sort(T* array, int size) { 89 | sort(array, size, LessThan_default()); } 90 | 91 | 92 | //================================================================================================= 93 | // For 'vec's: 94 | 95 | 96 | template void sort(vec& v, LessThan lt) { 97 | sort((T*)v, v.size(), lt); } 98 | template void sort(vec& v) { 99 | sort(v, LessThan_default()); } 100 | 101 | 102 | //================================================================================================= 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/Vec.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*******************************************************************************************[Vec.h] 9 | Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_Vec_h 29 | #define Minisat_Vec_h 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #include "minisat/mtl/IntTypes.h" 36 | #include "minisat/mtl/XAlloc.h" 37 | 38 | namespace Minisat { 39 | 40 | //================================================================================================= 41 | // Automatically resizable arrays 42 | // 43 | // NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) 44 | 45 | template 46 | class vec { 47 | public: 48 | typedef _Size Size; 49 | private: 50 | T* data; 51 | Size sz; 52 | Size cap; 53 | 54 | // Don't allow copying (error prone): 55 | vec& operator=(vec& other); 56 | vec (vec& other); 57 | 58 | static inline Size max(Size x, Size y){ return (x > y) ? x : y; } 59 | 60 | public: 61 | // Constructors: 62 | vec() : data(NULL), sz(0), cap(0) { } 63 | explicit vec(Size size) : data(NULL), sz(0), cap(0) { growTo(size); } 64 | vec(Size size, const T& pad) : data(NULL), sz(0), cap(0) { growTo(size, pad); } 65 | ~vec() { clear(true); } 66 | 67 | // Pointer to first element: 68 | operator T* (void) { return data; } 69 | 70 | // Size operations: 71 | Size size (void) const { return sz; } 72 | void shrink (Size nelems) { assert(nelems <= sz); for (Size i = 0; i < nelems; i++) sz--, data[sz].~T(); } 73 | void shrink_ (Size nelems) { assert(nelems <= sz); sz -= nelems; } 74 | int capacity (void) const { return cap; } 75 | void capacity (Size min_cap); 76 | void growTo (Size size); 77 | void growTo (Size size, const T& pad); 78 | void clear (bool dealloc = false); 79 | 80 | // Stack interface: 81 | void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; } 82 | //void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; } 83 | void push (const T& elem) { if (sz == cap) capacity(sz+1); new (&data[sz++]) T(elem); } 84 | void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; } 85 | void pop (void) { assert(sz > 0); sz--, data[sz].~T(); } 86 | // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but 87 | // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not 88 | // happen given the way capacities are calculated (below). Essentially, all capacities are 89 | // even, but INT_MAX is odd. 90 | 91 | const T& last (void) const { return data[sz-1]; } 92 | T& last (void) { return data[sz-1]; } 93 | 94 | // Vector interface: 95 | const T& operator [] (Size index) const { return data[index]; } 96 | T& operator [] (Size index) { return data[index]; } 97 | 98 | // Duplicatation (preferred instead): 99 | void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (Size i = 0; i < sz; i++) copy[i] = data[i]; } 100 | void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } 101 | }; 102 | 103 | 104 | template 105 | void vec::capacity(Size min_cap) { 106 | if (cap >= min_cap) return; 107 | Size add = max((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 108 | const Size size_max = std::numeric_limits::max(); 109 | if ( ((size_max <= std::numeric_limits::max()) && (add > size_max - cap)) 110 | || (((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) ) 111 | throw OutOfMemoryException(); 112 | } 113 | 114 | 115 | template 116 | void vec::growTo(Size size, const T& pad) { 117 | if (sz >= size) return; 118 | capacity(size); 119 | for (Size i = sz; i < size; i++) data[i] = pad; 120 | sz = size; } 121 | 122 | 123 | template 124 | void vec::growTo(Size size) { 125 | if (sz >= size) return; 126 | capacity(size); 127 | for (Size i = sz; i < size; i++) new (&data[i]) T(); 128 | sz = size; } 129 | 130 | 131 | template 132 | void vec::clear(bool dealloc) { 133 | if (data != NULL){ 134 | for (Size i = 0; i < sz; i++) data[i].~T(); 135 | sz = 0; 136 | if (dealloc) free(data), data = NULL, cap = 0; } } 137 | 138 | //================================================================================================= 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /minisat/minisat/mtl/XAlloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /****************************************************************************************[XAlloc.h] 9 | Copyright (c) 2009-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | 28 | #ifndef Minisat_XAlloc_h 29 | #define Minisat_XAlloc_h 30 | 31 | #include 32 | #include 33 | 34 | namespace Minisat { 35 | 36 | //================================================================================================= 37 | // Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: 38 | 39 | class OutOfMemoryException{}; 40 | static inline void* xrealloc(void *ptr, size_t size) 41 | { 42 | void* mem = realloc(ptr, size); 43 | if (mem == NULL && errno == ENOMEM){ 44 | throw OutOfMemoryException(); 45 | }else 46 | return mem; 47 | } 48 | 49 | //================================================================================================= 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /minisat/minisat/simp/Main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /*****************************************************************************************[Main.cc] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #include 29 | #include 30 | 31 | #include "minisat/utils/System.h" 32 | #include "minisat/utils/ParseUtils.h" 33 | #include "minisat/utils/Options.h" 34 | #include "minisat/core/Dimacs.h" 35 | #include "minisat/simp/SimpSolver.h" 36 | 37 | using namespace Minisat; 38 | 39 | //================================================================================================= 40 | 41 | 42 | static Solver* solver; 43 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 44 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 45 | static void SIGINT_interrupt(int) { solver->interrupt(); } 46 | 47 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 48 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 49 | // functions are guarded by locks for multithreaded use). 50 | static void SIGINT_exit(int) { 51 | printf("\n"); printf("*** INTERRUPTED ***\n"); 52 | if (solver->verbosity > 0){ 53 | solver->printStats(); 54 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 55 | _exit(1); } 56 | 57 | 58 | //================================================================================================= 59 | // Main: 60 | 61 | int main(int argc, char** argv) 62 | { 63 | try { 64 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 65 | setX86FPUPrecision(); 66 | 67 | // Extra options: 68 | // 69 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 70 | BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true); 71 | BoolOption solve ("MAIN", "solve", "Completely turn on/off solving after preprocessing.", true); 72 | StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file."); 73 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", 0, IntRange(0, INT32_MAX)); 74 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", 0, IntRange(0, INT32_MAX)); 75 | BoolOption strictp("MAIN", "strict", "Validate DIMACS header during parsing.", false); 76 | 77 | parseOptions(argc, argv, true); 78 | 79 | SimpSolver S; 80 | double initial_time = cpuTime(); 81 | 82 | if (!pre) S.eliminate(true); 83 | 84 | S.verbosity = verb; 85 | 86 | solver = &S; 87 | // Use signal handlers that forcibly quit until the solver will be able to respond to 88 | // interrupts: 89 | sigTerm(SIGINT_exit); 90 | 91 | // Try to set resource limits: 92 | if (cpu_lim != 0) limitTime(cpu_lim); 93 | if (mem_lim != 0) limitMemory(mem_lim); 94 | 95 | if (argc == 1) 96 | printf("Reading from standard input... Use '--help' for help.\n"); 97 | 98 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 99 | if (in == NULL) 100 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 101 | 102 | if (S.verbosity > 0){ 103 | printf("============================[ Problem Statistics ]=============================\n"); 104 | printf("| |\n"); } 105 | 106 | parse_DIMACS(in, S, (bool)strictp); 107 | gzclose(in); 108 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 109 | 110 | if (S.verbosity > 0){ 111 | printf("| Number of variables: %12d |\n", S.nVars()); 112 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 113 | 114 | double parsed_time = cpuTime(); 115 | if (S.verbosity > 0) 116 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 117 | 118 | // Change to signal-handlers that will only notify the solver and allow it to terminate 119 | // voluntarily: 120 | sigTerm(SIGINT_interrupt); 121 | 122 | S.eliminate(true); 123 | double simplified_time = cpuTime(); 124 | if (S.verbosity > 0){ 125 | printf("| Simplification time: %12.2f s |\n", simplified_time - parsed_time); 126 | printf("| |\n"); } 127 | 128 | if (!S.okay()){ 129 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 130 | if (S.verbosity > 0){ 131 | printf("===============================================================================\n"); 132 | printf("Solved by simplification\n"); 133 | S.printStats(); 134 | printf("\n"); } 135 | printf("UNSATISFIABLE\n"); 136 | exit(20); 137 | } 138 | 139 | lbool ret = l_Undef; 140 | 141 | if (solve){ 142 | vec dummy; 143 | // Comments by Fei: Now the solveLimited() function really just initialize the problem. It needs steps to finish up! 144 | ret = S.solveLimited(dummy); 145 | while (S.env_hold) { // Comments by Fei: SAT is not solved yet! it is on hold 146 | S.agent_decision = S.default_pickLit(); // Comments by Fei: set up agent_decision (for now it is the same as pickBranchLit heuristics) 147 | ret = S.step(); // this is doing one more step! 148 | } 149 | }else if (S.verbosity > 0) 150 | printf("===============================================================================\n"); 151 | 152 | if (dimacs && ret == l_Undef) 153 | S.toDimacs((const char*)dimacs); 154 | 155 | if (S.verbosity > 0){ 156 | S.printStats(); 157 | printf("\n"); } 158 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 159 | if (res != NULL){ 160 | if (ret == l_True){ 161 | fprintf(res, "SAT\n"); 162 | for (int i = 0; i < S.nVars(); i++) 163 | if (S.model[i] != l_Undef) { 164 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);} 165 | fprintf(res, " 0\n"); 166 | }else if (ret == l_False) 167 | fprintf(res, "UNSAT\n"); 168 | else 169 | fprintf(res, "INDET\n"); 170 | fclose(res); 171 | } 172 | 173 | #ifdef NDEBUG 174 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 175 | #else 176 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 177 | #endif 178 | } catch (OutOfMemoryException&){ 179 | printf("===============================================================================\n"); 180 | printf("INDETERMINATE\n"); 181 | exit(0); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /minisat/minisat/simp/SimpSolver.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /************************************************************************************[SimpSolver.h] 9 | Copyright (c) 2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_SimpSolver_h 29 | #define Minisat_SimpSolver_h 30 | 31 | #include "minisat/mtl/Queue.h" 32 | #include "minisat/core/Solver.h" 33 | 34 | 35 | namespace Minisat { 36 | 37 | //================================================================================================= 38 | 39 | 40 | class SimpSolver : public Solver { 41 | public: 42 | // Constructor/Destructor: 43 | // 44 | SimpSolver(); 45 | ~SimpSolver(); 46 | 47 | // Problem specification: 48 | // 49 | Var newVar (lbool upol = l_Undef, bool dvar = true); 50 | void releaseVar(Lit l); 51 | bool addClause (const vec& ps); 52 | bool addEmptyClause(); // Add the empty clause to the solver. 53 | bool addClause (Lit p); // Add a unit clause to the solver. 54 | bool addClause (Lit p, Lit q); // Add a binary clause to the solver. 55 | bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. 56 | bool addClause (Lit p, Lit q, Lit r, Lit s); // Add a quaternary clause to the solver. 57 | bool addClause_( vec& ps); 58 | bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction). 59 | 60 | // Variable mode: 61 | // 62 | void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated. 63 | bool isEliminated(Var v) const; 64 | 65 | // Alternative freeze interface (may replace 'setFrozen()'): 66 | void freezeVar (Var v); // Freeze one variable so it will not be eliminated. 67 | void thaw (); // Thaw all frozen variables. 68 | 69 | 70 | // Solving: 71 | // 72 | bool solve (const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 73 | lbool solveLimited(const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 74 | bool solve ( bool do_simp = true, bool turn_off_simp = false); 75 | bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false); 76 | bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false); 77 | bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false); 78 | bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification. 79 | 80 | // Memory managment: 81 | // 82 | virtual void garbageCollect(); 83 | 84 | 85 | // Generate a (possibly simplified) DIMACS file: 86 | // 87 | #if 0 88 | void toDimacs (const char* file, const vec& assumps); 89 | void toDimacs (const char* file); 90 | void toDimacs (const char* file, Lit p); 91 | void toDimacs (const char* file, Lit p, Lit q); 92 | void toDimacs (const char* file, Lit p, Lit q, Lit r); 93 | #endif 94 | 95 | // Mode of operation: 96 | // 97 | int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero). 98 | int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit. 99 | // -1 means no limit. 100 | int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit. 101 | double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac'). 102 | 103 | bool use_asymm; // Shrink clauses by asymmetric branching. 104 | bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :) 105 | bool use_elim; // Perform variable elimination. 106 | bool extend_model; // Flag to indicate whether the user needs to look at the full model. 107 | 108 | // Statistics: 109 | // 110 | int merges; 111 | int asymm_lits; 112 | int eliminated_vars; 113 | 114 | // Comments by Fei: step function 115 | lbool step() {return solve_();} 116 | 117 | 118 | protected: 119 | 120 | // Helper structures: 121 | // 122 | struct ElimLt { 123 | const LMap& n_occ; 124 | explicit ElimLt(const LMap& no) : n_occ(no) {} 125 | 126 | // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating 127 | // 32-bit implementation instead then, but this will have to do for now. 128 | uint64_t cost (Var x) const { return (uint64_t)n_occ[mkLit(x)] * (uint64_t)n_occ[~mkLit(x)]; } 129 | bool operator()(Var x, Var y) const { return cost(x) < cost(y); } 130 | 131 | // TODO: investigate this order alternative more. 132 | // bool operator()(Var x, Var y) const { 133 | // int c_x = cost(x); 134 | // int c_y = cost(y); 135 | // return c_x < c_y || c_x == c_y && x < y; } 136 | }; 137 | 138 | struct ClauseDeleted { 139 | const ClauseAllocator& ca; 140 | explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {} 141 | bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } }; 142 | 143 | // Solver state: 144 | // 145 | int elimorder; 146 | bool use_simplification; 147 | Var max_simp_var; // Max variable at the point simplification was turned off. 148 | vec elimclauses; 149 | VMap touched; 150 | OccLists, ClauseDeleted> 151 | occurs; 152 | LMap n_occ; 153 | Heap elim_heap; 154 | Queue subsumption_queue; 155 | VMap frozen; 156 | vec frozen_vars; 157 | VMap eliminated; 158 | int bwdsub_assigns; 159 | int n_touched; 160 | 161 | // Temporaries: 162 | // 163 | CRef bwdsub_tmpunit; 164 | 165 | // Main internal methods: 166 | // 167 | lbool solve_ (bool do_simp = true, bool turn_off_simp = false); 168 | bool asymm (Var v, CRef cr); 169 | bool asymmVar (Var v); 170 | void updateElimHeap (Var v); 171 | void gatherTouchedClauses (); 172 | bool merge (const Clause& _ps, const Clause& _qs, Var v, vec& out_clause); 173 | bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size); 174 | bool backwardSubsumptionCheck (bool verbose = false); 175 | bool eliminateVar (Var v); 176 | void extendModel (); 177 | 178 | void removeClause (CRef cr); 179 | bool strengthenClause (CRef cr, Lit l); 180 | bool implied (const vec& c); 181 | void relocAll (ClauseAllocator& to); 182 | }; 183 | 184 | 185 | //================================================================================================= 186 | // Implementation of inline methods: 187 | 188 | 189 | inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; } 190 | inline void SimpSolver::updateElimHeap(Var v) { 191 | assert(use_simplification); 192 | // if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef) 193 | if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)) 194 | elim_heap.update(v); } 195 | 196 | 197 | inline bool SimpSolver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } 198 | inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); } 199 | inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } 200 | inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } 201 | inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } 202 | inline bool SimpSolver::addClause (Lit p, Lit q, Lit r, Lit s){ add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); add_tmp.push(s); return addClause_(add_tmp); } 203 | inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } } 204 | 205 | inline void SimpSolver::freezeVar(Var v){ 206 | if (!frozen[v]){ 207 | frozen[v] = 1; 208 | frozen_vars.push(v); 209 | } } 210 | 211 | inline void SimpSolver::thaw(){ 212 | for (int i = 0; i < frozen_vars.size(); i++){ 213 | Var v = frozen_vars[i]; 214 | frozen[v] = 0; 215 | if (use_simplification) 216 | updateElimHeap(v); 217 | } 218 | frozen_vars.clear(); } 219 | 220 | inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; } 221 | inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; } 222 | inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; } 223 | inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; } 224 | inline bool SimpSolver::solve (const vec& assumps, bool do_simp, bool turn_off_simp){ 225 | budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; } 226 | 227 | inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bool turn_off_simp){ 228 | env_hold = false; env_reward = 0.0; state_mode = STATE_SOLVED; /*Comments by Fei: RL env init */ 229 | assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); } 230 | 231 | //================================================================================================= 232 | } 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /minisat/minisat/utils/Options.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /**************************************************************************************[Options.cc] 9 | Copyright (c) 2008-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | #include "minisat/mtl/Sort.h" 28 | #include "minisat/utils/Options.h" 29 | #include "minisat/utils/ParseUtils.h" 30 | 31 | using namespace Minisat; 32 | 33 | void Minisat::parseOptions(int& argc, char** argv, bool strict) 34 | { 35 | int i, j; 36 | for (i = j = 1; i < argc; i++){ 37 | const char* str = argv[i]; 38 | if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){ 39 | if (*str == '\0') 40 | printUsageAndExit(argc, argv); 41 | else if (match(str, "-verb")) 42 | printUsageAndExit(argc, argv, true); 43 | } else { 44 | bool parsed_ok = false; 45 | 46 | for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){ 47 | parsed_ok = Option::getOptionList()[k]->parse(argv[i]); 48 | 49 | // fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip"); 50 | } 51 | 52 | if (!parsed_ok){ 53 | if (strict && match(argv[i], "-")) 54 | fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1); 55 | else 56 | argv[j++] = argv[i]; 57 | } 58 | } 59 | } 60 | 61 | argc -= (i - j); 62 | } 63 | 64 | 65 | void Minisat::setUsageHelp (const char* str){ Option::getUsageString() = str; } 66 | void Minisat::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; } 67 | void Minisat::printUsageAndExit (int /*argc*/, char** argv, bool verbose) 68 | { 69 | const char* usage = Option::getUsageString(); 70 | if (usage != NULL) 71 | fprintf(stderr, usage, argv[0]); 72 | 73 | sort(Option::getOptionList(), Option::OptionLt()); 74 | 75 | const char* prev_cat = NULL; 76 | const char* prev_type = NULL; 77 | 78 | for (int i = 0; i < Option::getOptionList().size(); i++){ 79 | const char* cat = Option::getOptionList()[i]->category; 80 | const char* type = Option::getOptionList()[i]->type_name; 81 | 82 | if (cat != prev_cat) 83 | fprintf(stderr, "\n%s OPTIONS:\n\n", cat); 84 | else if (type != prev_type) 85 | fprintf(stderr, "\n"); 86 | 87 | Option::getOptionList()[i]->help(verbose); 88 | 89 | prev_cat = Option::getOptionList()[i]->category; 90 | prev_type = Option::getOptionList()[i]->type_name; 91 | } 92 | 93 | fprintf(stderr, "\nHELP OPTIONS:\n\n"); 94 | fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString()); 95 | fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString()); 96 | fprintf(stderr, "\n"); 97 | exit(0); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /minisat/minisat/utils/Options.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /***************************************************************************************[Options.h] 9 | Copyright (c) 2008-2010, Niklas Sorensson 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 12 | associated documentation files (the "Software"), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 14 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all copies or 18 | substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 21 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 23 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 24 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | **************************************************************************************************/ 26 | 27 | #ifndef Minisat_Options_h 28 | #define Minisat_Options_h 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "minisat/mtl/IntTypes.h" 36 | #include "minisat/mtl/Vec.h" 37 | #include "minisat/utils/ParseUtils.h" 38 | 39 | namespace Minisat { 40 | 41 | //================================================================================================== 42 | // Top-level option parse/help functions: 43 | 44 | 45 | extern void parseOptions (int& argc, char** argv, bool strict = false); 46 | extern void printUsageAndExit(int argc, char** argv, bool verbose = false); 47 | extern void setUsageHelp (const char* str); 48 | extern void setHelpPrefixStr (const char* str); 49 | 50 | 51 | //================================================================================================== 52 | // Options is an abstract class that gives the interface for all types options: 53 | 54 | 55 | class Option 56 | { 57 | protected: 58 | const char* name; 59 | const char* description; 60 | const char* category; 61 | const char* type_name; 62 | 63 | static vec& getOptionList () { static vec options; return options; } 64 | static const char*& getUsageString() { static const char* usage_str; return usage_str; } 65 | static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } 66 | 67 | struct OptionLt { 68 | bool operator()(const Option* x, const Option* y) { 69 | int test1 = strcmp(x->category, y->category); 70 | return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); 71 | } 72 | }; 73 | 74 | Option(const char* name_, 75 | const char* desc_, 76 | const char* cate_, 77 | const char* type_) : 78 | name (name_) 79 | , description(desc_) 80 | , category (cate_) 81 | , type_name (type_) 82 | { 83 | getOptionList().push(this); 84 | } 85 | 86 | public: 87 | virtual ~Option() {} 88 | 89 | virtual bool parse (const char* str) = 0; 90 | virtual void help (bool verbose = false) = 0; 91 | 92 | friend void parseOptions (int& argc, char** argv, bool strict); 93 | friend void printUsageAndExit (int argc, char** argv, bool verbose); 94 | friend void setUsageHelp (const char* str); 95 | friend void setHelpPrefixStr (const char* str); 96 | }; 97 | 98 | 99 | //================================================================================================== 100 | // Range classes with specialization for floating types: 101 | 102 | 103 | struct IntRange { 104 | int begin; 105 | int end; 106 | IntRange(int b, int e) : begin(b), end(e) {} 107 | }; 108 | 109 | struct Int64Range { 110 | int64_t begin; 111 | int64_t end; 112 | Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} 113 | }; 114 | 115 | struct DoubleRange { 116 | double begin; 117 | double end; 118 | bool begin_inclusive; 119 | bool end_inclusive; 120 | DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} 121 | }; 122 | 123 | 124 | //================================================================================================== 125 | // Double options: 126 | 127 | 128 | class DoubleOption : public Option 129 | { 130 | protected: 131 | DoubleRange range; 132 | double value; 133 | 134 | public: 135 | DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) 136 | : Option(n, d, c, ""), range(r), value(def) { 137 | // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. 138 | } 139 | 140 | operator double (void) const { return value; } 141 | operator double& (void) { return value; } 142 | DoubleOption& operator=(double x) { value = x; return *this; } 143 | 144 | virtual bool parse(const char* str){ 145 | const char* span = str; 146 | 147 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 148 | return false; 149 | 150 | char* end; 151 | double tmp = strtod(span, &end); 152 | 153 | if (end == NULL) 154 | return false; 155 | else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ 156 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 157 | exit(1); 158 | }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ 159 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 160 | exit(1); } 161 | 162 | value = tmp; 163 | // fprintf(stderr, "READ VALUE: %g\n", value); 164 | 165 | return true; 166 | } 167 | 168 | virtual void help (bool verbose = false){ 169 | fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", 170 | name, type_name, 171 | range.begin_inclusive ? '[' : '(', 172 | range.begin, 173 | range.end, 174 | range.end_inclusive ? ']' : ')', 175 | value); 176 | if (verbose){ 177 | fprintf(stderr, "\n %s\n", description); 178 | fprintf(stderr, "\n"); 179 | } 180 | } 181 | }; 182 | 183 | 184 | //================================================================================================== 185 | // Int options: 186 | 187 | 188 | class IntOption : public Option 189 | { 190 | protected: 191 | IntRange range; 192 | int32_t value; 193 | 194 | public: 195 | IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) 196 | : Option(n, d, c, ""), range(r), value(def) {} 197 | 198 | operator int32_t (void) const { return value; } 199 | operator int32_t& (void) { return value; } 200 | IntOption& operator= (int32_t x) { value = x; return *this; } 201 | 202 | virtual bool parse(const char* str){ 203 | const char* span = str; 204 | 205 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 206 | return false; 207 | 208 | char* end; 209 | int32_t tmp = strtol(span, &end, 10); 210 | 211 | if (end == NULL) 212 | return false; 213 | else if (tmp > range.end){ 214 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 215 | exit(1); 216 | }else if (tmp < range.begin){ 217 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 218 | exit(1); } 219 | 220 | value = tmp; 221 | 222 | return true; 223 | } 224 | 225 | virtual void help (bool verbose = false){ 226 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 227 | if (range.begin == INT32_MIN) 228 | fprintf(stderr, "imin"); 229 | else 230 | fprintf(stderr, "%4d", range.begin); 231 | 232 | fprintf(stderr, " .. "); 233 | if (range.end == INT32_MAX) 234 | fprintf(stderr, "imax"); 235 | else 236 | fprintf(stderr, "%4d", range.end); 237 | 238 | fprintf(stderr, "] (default: %d)\n", value); 239 | if (verbose){ 240 | fprintf(stderr, "\n %s\n", description); 241 | fprintf(stderr, "\n"); 242 | } 243 | } 244 | }; 245 | 246 | 247 | // Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. 248 | #ifndef _MSC_VER 249 | 250 | class Int64Option : public Option 251 | { 252 | protected: 253 | Int64Range range; 254 | int64_t value; 255 | 256 | public: 257 | Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) 258 | : Option(n, d, c, ""), range(r), value(def) {} 259 | 260 | operator int64_t (void) const { return value; } 261 | operator int64_t& (void) { return value; } 262 | Int64Option& operator= (int64_t x) { value = x; return *this; } 263 | 264 | virtual bool parse(const char* str){ 265 | const char* span = str; 266 | 267 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 268 | return false; 269 | 270 | char* end; 271 | int64_t tmp = strtoll(span, &end, 10); 272 | 273 | if (end == NULL) 274 | return false; 275 | else if (tmp > range.end){ 276 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 277 | exit(1); 278 | }else if (tmp < range.begin){ 279 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 280 | exit(1); } 281 | 282 | value = tmp; 283 | 284 | return true; 285 | } 286 | 287 | virtual void help (bool verbose = false){ 288 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 289 | if (range.begin == INT64_MIN) 290 | fprintf(stderr, "imin"); 291 | else 292 | fprintf(stderr, "%4"PRIi64, range.begin); 293 | 294 | fprintf(stderr, " .. "); 295 | if (range.end == INT64_MAX) 296 | fprintf(stderr, "imax"); 297 | else 298 | fprintf(stderr, "%4"PRIi64, range.end); 299 | 300 | fprintf(stderr, "] (default: %"PRIi64")\n", value); 301 | if (verbose){ 302 | fprintf(stderr, "\n %s\n", description); 303 | fprintf(stderr, "\n"); 304 | } 305 | } 306 | }; 307 | #endif 308 | 309 | //================================================================================================== 310 | // String option: 311 | 312 | 313 | class StringOption : public Option 314 | { 315 | const char* value; 316 | public: 317 | StringOption(const char* c, const char* n, const char* d, const char* def = NULL) 318 | : Option(n, d, c, ""), value(def) {} 319 | 320 | operator const char* (void) const { return value; } 321 | operator const char*& (void) { return value; } 322 | StringOption& operator= (const char* x) { value = x; return *this; } 323 | 324 | virtual bool parse(const char* str){ 325 | const char* span = str; 326 | 327 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 328 | return false; 329 | 330 | value = span; 331 | return true; 332 | } 333 | 334 | virtual void help (bool verbose = false){ 335 | fprintf(stderr, " -%-10s = %8s\n", name, type_name); 336 | if (verbose){ 337 | fprintf(stderr, "\n %s\n", description); 338 | fprintf(stderr, "\n"); 339 | } 340 | } 341 | }; 342 | 343 | 344 | //================================================================================================== 345 | // Bool option: 346 | 347 | 348 | class BoolOption : public Option 349 | { 350 | bool value; 351 | 352 | public: 353 | BoolOption(const char* c, const char* n, const char* d, bool v) 354 | : Option(n, d, c, ""), value(v) {} 355 | 356 | operator bool (void) const { return value; } 357 | operator bool& (void) { return value; } 358 | BoolOption& operator=(bool b) { value = b; return *this; } 359 | 360 | virtual bool parse(const char* str){ 361 | const char* span = str; 362 | 363 | if (match(span, "-")){ 364 | bool b = !match(span, "no-"); 365 | 366 | if (strcmp(span, name) == 0){ 367 | value = b; 368 | return true; } 369 | } 370 | 371 | return false; 372 | } 373 | 374 | virtual void help (bool verbose = false){ 375 | 376 | fprintf(stderr, " -%s, -no-%s", name, name); 377 | 378 | for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) 379 | fprintf(stderr, " "); 380 | 381 | fprintf(stderr, " "); 382 | fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); 383 | if (verbose){ 384 | fprintf(stderr, "\n %s\n", description); 385 | fprintf(stderr, "\n"); 386 | } 387 | } 388 | }; 389 | 390 | //================================================================================================= 391 | } 392 | 393 | #endif 394 | -------------------------------------------------------------------------------- /minisat/minisat/utils/ParseUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /************************************************************************************[ParseUtils.h] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_ParseUtils_h 29 | #define Minisat_ParseUtils_h 30 | 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | #include "minisat/mtl/XAlloc.h" 37 | 38 | namespace Minisat { 39 | 40 | //------------------------------------------------------------------------------------------------- 41 | // A simple buffered character stream class: 42 | 43 | 44 | 45 | class StreamBuffer { 46 | gzFile in; 47 | unsigned char* buf; 48 | int pos; 49 | int size; 50 | 51 | enum { buffer_size = 64*1024 }; 52 | 53 | void assureLookahead() { 54 | if (pos >= size) { 55 | pos = 0; 56 | size = gzread(in, buf, buffer_size); } } 57 | 58 | public: 59 | explicit StreamBuffer(gzFile i) : in(i), pos(0), size(0){ 60 | buf = (unsigned char*)xrealloc(NULL, buffer_size); 61 | assureLookahead(); 62 | } 63 | ~StreamBuffer() { free(buf); } 64 | 65 | int operator * () const { return (pos >= size) ? EOF : buf[pos]; } 66 | void operator ++ () { pos++; assureLookahead(); } 67 | int position () const { return pos; } 68 | }; 69 | 70 | 71 | //------------------------------------------------------------------------------------------------- 72 | // End-of-file detection functions for StreamBuffer and char*: 73 | 74 | 75 | static inline bool isEof(StreamBuffer& in) { return *in == EOF; } 76 | static inline bool isEof(const char* in) { return *in == '\0'; } 77 | 78 | //------------------------------------------------------------------------------------------------- 79 | // Generic parse functions parametrized over the input-stream type. 80 | 81 | 82 | template 83 | static void skipWhitespace(B& in) { 84 | while ((*in >= 9 && *in <= 13) || *in == 32) 85 | ++in; } 86 | 87 | 88 | template 89 | static void skipLine(B& in) { 90 | for (;;){ 91 | if (isEof(in)) return; 92 | if (*in == '\n') { ++in; return; } 93 | ++in; } } 94 | 95 | 96 | template 97 | static int parseInt(B& in) { 98 | int val = 0; 99 | bool neg = false; 100 | skipWhitespace(in); 101 | if (*in == '-') neg = true, ++in; 102 | else if (*in == '+') ++in; 103 | if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 104 | while (*in >= '0' && *in <= '9') 105 | val = val*10 + (*in - '0'), 106 | ++in; 107 | return neg ? -val : val; } 108 | 109 | 110 | // String matching: in case of a match the input iterator will be advanced the corresponding 111 | // number of characters. 112 | template 113 | static bool match(B& in, const char* str) { 114 | int i; 115 | for (i = 0; str[i] != '\0'; i++) 116 | if (in[i] != str[i]) 117 | return false; 118 | 119 | in += i; 120 | 121 | return true; 122 | } 123 | 124 | // String matching: consumes characters eagerly, but does not require random access iterator. 125 | template 126 | static bool eagerMatch(B& in, const char* str) { 127 | for (; *str != '\0'; ++str, ++in) 128 | if (*str != *in) 129 | return false; 130 | return true; } 131 | 132 | 133 | //================================================================================================= 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /minisat/minisat/utils/System.cc: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /***************************************************************************************[System.cc] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #include 29 | #include 30 | 31 | #include "minisat/utils/System.h" 32 | 33 | #if defined(__linux__) 34 | 35 | #include 36 | 37 | using namespace Minisat; 38 | 39 | static inline int memReadStat(int field) 40 | { 41 | char name[256]; 42 | pid_t pid = getpid(); 43 | int value; 44 | 45 | sprintf(name, "/proc/%d/statm", pid); 46 | FILE* in = fopen(name, "rb"); 47 | if (in == NULL) return 0; 48 | 49 | for (; field >= 0; field--) 50 | if (fscanf(in, "%d", &value) != 1) 51 | printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1); 52 | fclose(in); 53 | return value; 54 | } 55 | 56 | 57 | static inline int memReadPeak(void) 58 | { 59 | char name[256]; 60 | pid_t pid = getpid(); 61 | 62 | sprintf(name, "/proc/%d/status", pid); 63 | FILE* in = fopen(name, "rb"); 64 | if (in == NULL) return 0; 65 | 66 | // Find the correct line, beginning with "VmPeak:": 67 | int peak_kb = 0; 68 | while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) 69 | while (!feof(in) && fgetc(in) != '\n') 70 | ; 71 | fclose(in); 72 | 73 | return peak_kb; 74 | } 75 | 76 | double Minisat::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); } 77 | double Minisat::memUsedPeak(bool strictlyPeak) { 78 | double peak = memReadPeak() / (double)1024; 79 | return peak == 0 && !strictlyPeak ? memUsed() : peak; } 80 | 81 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__gnu_hurd__) 82 | 83 | double Minisat::memUsed() { 84 | struct rusage ru; 85 | getrusage(RUSAGE_SELF, &ru); 86 | return (double)ru.ru_maxrss / 1024; } 87 | double Minisat::memUsedPeak() { return memUsed(); } 88 | 89 | 90 | #elif defined(__APPLE__) 91 | #include 92 | 93 | double Minisat::memUsed() { 94 | malloc_statistics_t t; 95 | malloc_zone_statistics(NULL, &t); 96 | return (double)t.max_size_in_use / (1024*1024); } 97 | double Minisat::memUsedPeak() { return memUsed(); } 98 | 99 | #else 100 | double Minisat::memUsed() { return 0; } 101 | double Minisat::memUsedPeak() { return 0; } 102 | #endif 103 | 104 | 105 | void Minisat::setX86FPUPrecision() 106 | { 107 | #if defined(__linux__) && defined(_FPU_EXTENDED) && defined(_FPU_DOUBLE) && defined(_FPU_GETCW) 108 | // Only correct FPU precision on Linux architectures that needs and supports it: 109 | fpu_control_t oldcw, newcw; 110 | _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); 111 | printf("WARNING: for repeatability, setting FPU to use double precision\n"); 112 | #endif 113 | } 114 | 115 | 116 | #if !defined(_MSC_VER) && !defined(__MINGW32__) 117 | void Minisat::limitMemory(uint64_t max_mem_mb) 118 | { 119 | // FIXME: OpenBSD does not support RLIMIT_AS. Not sure how well RLIMIT_DATA works instead. 120 | #if defined(__OpenBSD__) 121 | #define RLIMIT_AS RLIMIT_DATA 122 | #endif 123 | 124 | // Set limit on virtual memory: 125 | if (max_mem_mb != 0){ 126 | rlim_t new_mem_lim = (rlim_t)max_mem_mb * 1024*1024; 127 | rlimit rl; 128 | getrlimit(RLIMIT_AS, &rl); 129 | if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ 130 | rl.rlim_cur = new_mem_lim; 131 | if (setrlimit(RLIMIT_AS, &rl) == -1) 132 | printf("WARNING! Could not set resource limit: Virtual memory.\n"); 133 | } 134 | } 135 | 136 | #if defined(__OpenBSD__) 137 | #undef RLIMIT_AS 138 | #endif 139 | } 140 | #else 141 | void Minisat::limitMemory(uint64_t /*max_mem_mb*/) 142 | { 143 | printf("WARNING! Memory limit not supported on this architecture.\n"); 144 | } 145 | #endif 146 | 147 | 148 | #if !defined(_MSC_VER) && !defined(__MINGW32__) 149 | void Minisat::limitTime(uint32_t max_cpu_time) 150 | { 151 | if (max_cpu_time != 0){ 152 | rlimit rl; 153 | getrlimit(RLIMIT_CPU, &rl); 154 | if (rl.rlim_max == RLIM_INFINITY || (rlim_t)max_cpu_time < rl.rlim_max){ 155 | rl.rlim_cur = max_cpu_time; 156 | if (setrlimit(RLIMIT_CPU, &rl) == -1) 157 | printf("WARNING! Could not set resource limit: CPU-time.\n"); 158 | } 159 | } 160 | } 161 | #else 162 | void Minisat::limitTime(uint32_t /*max_cpu_time*/) 163 | { 164 | printf("WARNING! CPU-time limit not supported on this architecture.\n"); 165 | } 166 | #endif 167 | 168 | 169 | void Minisat::sigTerm(void handler(int)) 170 | { 171 | signal(SIGINT, handler); 172 | signal(SIGTERM,handler); 173 | #ifdef SIGXCPU 174 | signal(SIGXCPU,handler); 175 | #endif 176 | } 177 | -------------------------------------------------------------------------------- /minisat/minisat/utils/System.h: -------------------------------------------------------------------------------- 1 | /* 2 | ################################################################################################################################# 3 | # All the source files in `minisat` folder were initially copied and later modified from https://github.com/feiwang3311/minisat # 4 | # (which was taken from the MiniSat source at https://github.com/niklasso/minisat). The MiniSAT license is below. # 5 | ################################################################################################################################# 6 | */ 7 | 8 | /****************************************************************************************[System.h] 9 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 10 | Copyright (c) 2007-2010, Niklas Sorensson 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 13 | associated documentation files (the "Software"), to deal in the Software without restriction, 14 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 15 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all copies or 19 | substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 22 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 24 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 25 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | **************************************************************************************************/ 27 | 28 | #ifndef Minisat_System_h 29 | #define Minisat_System_h 30 | 31 | #if defined(__linux__) 32 | #include 33 | #endif 34 | 35 | #include "minisat/mtl/IntTypes.h" 36 | 37 | //------------------------------------------------------------------------------------------------- 38 | 39 | namespace Minisat { 40 | 41 | static inline double cpuTime(void); // CPU-time in seconds. 42 | 43 | extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures). 44 | extern double memUsedPeak(bool strictlyPeak = false); // Peak-memory in mega bytes (returns 0 for unsupported architectures). 45 | 46 | extern void setX86FPUPrecision(); // Make sure double's are represented with the same precision 47 | // in memory and registers. 48 | 49 | extern void limitMemory(uint64_t max_mem_mb); // Set a limit on total memory usage. The exact 50 | // semantics varies depending on architecture. 51 | 52 | extern void limitTime(uint32_t max_cpu_time); // Set a limit on maximum CPU time. The exact 53 | // semantics varies depending on architecture. 54 | 55 | extern void sigTerm(void handler(int)); // Set up handling of available termination signals. 56 | 57 | } 58 | 59 | //------------------------------------------------------------------------------------------------- 60 | // Implementation of inline functions: 61 | 62 | #if defined(_MSC_VER) || defined(__MINGW32__) 63 | #include 64 | 65 | static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } 66 | 67 | #else 68 | #include 69 | #include 70 | #include 71 | 72 | static inline double Minisat::cpuTime(void) { 73 | struct rusage ru; 74 | getrusage(RUSAGE_SELF, &ru); 75 | return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } 76 | 77 | #endif 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /train.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Nvidia Corporation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | python3 dqn.py \ 16 | --logdir ./log \ 17 | --env-name sat-v0 \ 18 | --train-problems-paths ./data/uf50-218-tvt/train \ 19 | --eval-problems-paths ./data/uf50-218-tvt/validation \ 20 | --lr 0.00002 \ 21 | --bsize 64 \ 22 | --buffer-size 20000 \ 23 | --eps-init 1.0 \ 24 | --eps-final 0.01 \ 25 | --gamma 0.99 \ 26 | --eps-decay-steps 30000 \ 27 | --batch-updates 50000 \ 28 | --history-len 1 \ 29 | --init-exploration-steps 5000 \ 30 | --step-freq 4 \ 31 | --target-update-freq 10 \ 32 | --loss mse \ 33 | --opt adam \ 34 | --save-freq 500 \ 35 | --grad_clip 1 \ 36 | --grad_clip_norm_type 2 \ 37 | --eval-freq 1000 \ 38 | --eval-time-limit 3600 \ 39 | --core-steps 4 \ 40 | --expert-exploration-prob 0.0 \ 41 | --priority_alpha 0.5 \ 42 | --priority_beta 0.5 \ 43 | --e2v-aggregator sum \ 44 | --n_hidden 1 \ 45 | --hidden_size 64 \ 46 | --decoder_v_out_size 32 \ 47 | --decoder_e_out_size 1 \ 48 | --decoder_g_out_size 1 \ 49 | --encoder_v_out_size 32 \ 50 | --encoder_e_out_size 32 \ 51 | --encoder_g_out_size 32 \ 52 | --core_v_out_size 64 \ 53 | --core_e_out_size 64 \ 54 | --core_g_out_size 32 \ 55 | --activation relu \ 56 | --penalty_size 0.1 \ 57 | --train_time_max_decisions_allowed 500 \ 58 | --test_time_max_decisions_allowed 500 \ 59 | --no_max_cap_fill_buffer \ 60 | --lr_scheduler_gamma 1 \ 61 | --lr_scheduler_frequency 3000 \ 62 | --independent_block_layers 0 63 | --------------------------------------------------------------------------------