1 #include <iostream>
2 #include <algorithm>
3 #include "mmn_csp_solver.h"
4 //:
5 // \file
6 // \brief see if the Constraint Satisfaction Problem is satisfiable
7 // \author Martin Roberts
8
9 #ifdef _MSC_VER
10 # include "vcl_msvc_warnings.h"
11 #endif
12 #include <cassert>
13
14 //: Default constructor
mmn_csp_solver()15 mmn_csp_solver::mmn_csp_solver() { init(); }
16
17 //: Construct with arcs
mmn_csp_solver(unsigned num_nodes,const std::vector<mmn_arc> & arcs)18 mmn_csp_solver::mmn_csp_solver(unsigned num_nodes,const std::vector<mmn_arc>& arcs):
19 nnodes_(num_nodes),verbose_(false)
20 {
21 init();
22 set_arcs(num_nodes,arcs);
23 }
24
init()25 void mmn_csp_solver::init()
26 {
27 }
28
29 //: Pass in the arcs, which are then used to build the graph object
set_arcs(unsigned num_nodes,const std::vector<mmn_arc> & arcs)30 void mmn_csp_solver::set_arcs(unsigned num_nodes,const std::vector<mmn_arc>& arcs)
31 {
32 nnodes_=num_nodes;
33 arcs_ = arcs;
34 //Verify consistency
35 unsigned max_node=0;
36 for (auto arc : arcs)
37 {
38 max_node=std::max(max_node,arc.max_v());
39 }
40 if (nnodes_ != max_node+1)
41 {
42 std::cerr<<"Arcs appear to be inconsistent with number of nodes in mmn_csp_solver::set_arcs\n"
43 <<"Max node in Arcs is: "<<max_node<<" but number of nodes= "<<nnodes_ << '\n';
44 }
45
46 graph_.build(nnodes_,arcs_);
47 }
48
49
50 //: Run the algorithm
operator ()(const std::vector<mmn_csp_solver::label_subset_t> & node_labels_subset,const std::vector<mmn_csp_solver::arc_labels_subset_t> & links_subset)51 bool mmn_csp_solver::operator()(const std::vector<mmn_csp_solver::label_subset_t >& node_labels_subset,
52 const std::vector<mmn_csp_solver::arc_labels_subset_t >& links_subset)
53 {
54 init();
55
56 node_labels_present_ = node_labels_subset;
57 initialise_arc_labels_linked(links_subset);
58
59
60 bool deletedNode=false;
61 bool deletedArc=false;
62
63 do
64 {
65 deletedNode = check_for_node_deletions();
66 deletedArc = check_for_arc_deletions();
67 }
68 while (deletedNode || deletedArc);
69
70 bool emptyKernel=true;
71
72 for (unsigned i=0; i<nnodes_;i++)
73 {
74 emptyKernel = emptyKernel && node_labels_present_[i].empty();
75 }
76
77 return !emptyKernel;
78 }
79
initialise_arc_labels_linked(const std::vector<mmn_csp_solver::arc_labels_subset_t> & links_subset)80 void mmn_csp_solver::initialise_arc_labels_linked(const std::vector<mmn_csp_solver::arc_labels_subset_t >& links_subset)
81 {
82 arc_labels_linked1_.clear();
83 arc_labels_linked2_.clear();
84 unsigned narcs=arcs_.size();
85 arc_labels_linked1_.resize(narcs);
86 arc_labels_linked2_.resize(narcs);
87
88 for (unsigned iarc=0;iarc<narcs;++iarc)
89 {
90 arc_labels_subset_t1& labels_linked1=arc_labels_linked1_[iarc];
91 arc_labels_subset_t2& labels_linked2=arc_labels_linked2_[iarc];
92
93 auto linkIter=links_subset[iarc].begin();
94 auto linkIterEnd=links_subset[iarc].end();
95 while (linkIter != linkIterEnd)
96 {
97 labels_linked1.insert(*linkIter);
98 labels_linked2.insert(*linkIter);
99 ++linkIter;
100 }
101 }
102 }
103
check_for_node_deletions()104 bool mmn_csp_solver::check_for_node_deletions()
105 {
106 bool deleted=false;
107 for (unsigned inode=0;inode<nnodes_;++inode)
108 {
109 auto labelIter=node_labels_present_[inode].begin();
110 auto labelIterEnd=node_labels_present_[inode].end();
111 const std::vector<std::pair<unsigned,unsigned> >& neighbourhood = graph_.node_data()[inode];
112 while (labelIter != labelIterEnd)
113 {
114 unsigned label = *labelIter; //this label value
115 //Now loop over all arcs in the node's neighbourhood
116 auto neighIter=neighbourhood.begin();
117 auto neighIterEnd=neighbourhood.end();
118 bool found=true;
119 while (neighIter != neighIterEnd)
120 {
121 bool foundThisNeighbour=false;
122 unsigned arcId=neighIter->second;
123 if (inode<neighIter->first)
124 {
125 std::pair<unsigned ,unsigned > sought(label,0);
126 auto linkIter=arc_labels_linked1_[arcId].lower_bound(sought);
127 if (linkIter != arc_labels_linked1_[arcId].end())
128 {
129 if (linkIter->first==label)
130 {
131 foundThisNeighbour=true;
132 }
133 }
134 }
135 else
136 {
137 std::pair<unsigned ,unsigned > sought(0,label);
138 auto linkIter=arc_labels_linked2_[arcId].lower_bound(sought);
139 if (linkIter != arc_labels_linked2_[arcId].end())
140 {
141 if (linkIter->second==label)
142 {
143 foundThisNeighbour=true;
144 }
145 }
146 }
147 found = found && foundThisNeighbour;
148 if (!foundThisNeighbour)
149 {
150 if (verbose_)
151 {
152 std::cout<<"Found no arc linking labels for node "<<inode<<" label "<<label<<" to node "<<neighIter->first<<"along arc ID "<<arcId<<std::endl;
153 }
154 break;
155 }
156 ++neighIter;
157 } //loop over all neighbours (pencils)
158
159 if (!found)
160 {
161 //Found no links from this label to anywhere
162 //So delete it
163 auto labelIterNext=labelIter;
164 ++labelIterNext;
165 if (verbose_)
166 {
167 std::cout<<"Have removed label "<<*labelIter<<" for node "<<inode<<" as it has no linking arcs"<<std::endl;
168 }
169 node_labels_present_[inode].erase(labelIter);
170 labelIter=labelIterNext;
171 deleted=true;
172 }
173 else
174 {
175 ++labelIter;
176 }
177 } //next label of this node (object)
178 } //next node (object)
179 return deleted;
180 }
181
check_for_arc_deletions()182 bool mmn_csp_solver::check_for_arc_deletions()
183 {
184 bool deleted=false;
185 for (unsigned iarc=0;iarc<arcs_.size();++iarc)
186 {
187 arc_labels_subset_t1& labels_linked1=arc_labels_linked1_[iarc];
188 arc_labels_subset_t2& labels_linked2=arc_labels_linked2_[iarc];
189 auto linkIter=labels_linked1.begin();
190 auto linkIterEnd=labels_linked1.end();
191 while (linkIter != linkIterEnd)
192 {
193 unsigned label1=linkIter->first;
194 unsigned label2=linkIter->second;
195 unsigned node1=arcs_[iarc].min_v();
196 unsigned node2=arcs_[iarc].max_v();
197 assert(node1<node2);
198 std::set<unsigned>& labelSet1=node_labels_present_[node1];
199
200 bool found=false;
201 if (labelSet1.find(label1)!=labelSet1.end())
202 {
203 std::set<unsigned>& labelSet2=node_labels_present_[node2];
204 found = labelSet2.find(label2)!=labelSet2.end();
205 }
206 if (!found) //failed to find at least one of target labels
207 {
208 deleted=true;
209 //std::pair<unsigned,unsigned > pair2(linkIter->second,linkIter->first); //transpose
210 std::pair<unsigned,unsigned > pair2(linkIter->first,linkIter->second); //transpose
211
212 labels_linked1.erase(linkIter++); //remove from multset 1
213 //Find all possible instances in multiset 2 for removal
214 std::pair<arc_labels_subset_t2::iterator,arc_labels_subset_t2::iterator> range=
215 labels_linked2.equal_range(pair2);
216 auto killer=range.first;
217
218 while (killer != range.second)
219 {
220 if (killer->first==pair2.first)
221 {
222 //remove target link
223 labels_linked2.erase(killer++);
224 if (verbose_)
225 {
226 std::cout<<"Have removed arc Id "<<iarc<<" Linking nodes "<<node1<<'\t'<<node2
227 <<" for respective labels "<<pair2.second<<'\t'<<pair2.first<<std::endl;
228 }
229 }
230 else
231 {
232 ++killer;
233 }
234 }
235 }
236 else
237 {
238 ++linkIter;
239 }
240 }
241 }
242 return deleted;
243 }
244