Exemplo n.º 1
0
	def _two(self, g, s1, cut1, val1):
		''' solves 2-decomposition '''
	
		# get root.
		root = g.graph['root']
	
		# greedy graph constraction.
		logging.info("two contracting")
		psz = len(g.nodes())
		while 1 == 1:
			test = False
			for e in g.edges():
				
				# graph active sets.
				sa = g.node[e[0]]['set']
				sb = g.node[e[1]]['set']
				
				# check if we cant merge.
				if len(sa) + len(sb) > self._cutoff: continue
				
				# dont touch root.
				if e[0] == root or e[1] == root: continue
					
				# make new node info.
				n = "%s_%s" % (str(e[0]), str(e[1]))
				s = g.node[e[0]]['set'].union(g.node[e[1]]['set'])			
				
				# insert into graph.
				g.add_node(n, {'set':s, 'graph':None})
				
				# rehook edges.
				for q in g.neighbors(e[0]):
					if q == e[1]: continue
					cut = g[e[0]][q]['cut']
					g.remove_edge(e[0], q)
					g.add_edge(n, q, {'cut':cut})

				for q in g.neighbors(e[1]):
					if q == e[0]: continue
					cut = g[e[1]][q]['cut']
					g.remove_edge(e[1], q)
					g.add_edge(n, q, {'cut':cut})		
					
				# do contraction.
				g.remove_edge(e[0], e[1])
				g.remove_node(e[0])
				g.remove_node(e[1])
					
				# break and reset.
				test = True
				break
				
			# check if there was no mod.
			if test == False:
				break				
		logging.info("two contracted: %i to %i" % (psz, len(g.nodes())))
		
		# solve bottom up.
		logging.info("solving two (bottom): %d" % len(s1))
		for p, q, kids in self._dfs_gen(g, root, order=False):
			
			# grab active set.
			s2 = g.node[p]['set']
			
			# if its the root just solve.
			if q == -1:
				
				# just solve.
				self._load(s2)
				if cut1 in s2:
					self._force(cut1, val1)
				sol, val = self._solve()
				self._clear()
				
				# save to root.
				g.node[p]['sol'] = sol
				g.node[p]['val'] = val
			
			else:
			
				# get cuts.
				cuts = g[p][q]['cut']
				
				# solve 4 combinations of orientations.
				for x, y in itertools.product([0,1], repeat=2):
					
					# solve.
					self._load(s2)
					if cut1 in s2:
						self._force(cut1, val1)
					self._force(cuts[0], x)
					self._force(cuts[1], y)
					sol, val = self._solve()
					self._clear()
					
					# save info.
					g.node[p]['sol_%i_%i' % (x,y)] = sol
					g.node[p]['val_%i_%i' % (x,y)] = val
				
		# prepare a partial solution.
		nlist = build_nlist(self._nodes, s1)
		blist = build_blist(self._bundles, s1)
		tlist = build_tlist(self._bundles, s1)
		partial = PartialSolution(nlist.size, blist.size)
		val = 0.0
							
		# apply solution top down.
		logging.info("applying two (top): %d" % len(s1))
		for p, q, kids in self._dfs_gen(g, root, order=True):
			
			# grab active set.
			s2 = g.node[p]['set']
			
			# just apply root.
			if q == -1:
				partial.merge(g.node[p]['sol'])
				val += g.node[p]['val']
				continue
			
				
			# determine what the parent did.
			cuts = g[p][q]['cut']
			oa = partial.get_orien(cuts[0])
			ob = partial.get_orien(cuts[1])
				
			# apply that solution.
			partial.merge(g.node[p]['sol_%i_%i' % (oa, ob)])
			val += g.node[p]['val_%i_%i' % (oa, ob)]
		
		# return the solution.
		return partial, val
Exemplo n.º 2
0
	def _one(self, g, s0):
		''' solves one component '''
		
		# greedy graph constraction.
		logging.info("one contracting")
		psz = len(g.nodes())
		while 1 == 1:
			test = False
			for e in g.edges():
				
				# graph active sets.
				sa = g.node[e[0]]['set']
				sb = g.node[e[1]]['set']
				
				# check if we cant merge.
				if len(sa) + len(sb) > self._cutoff: continue
					
				# make new node info.
				n = "%s_%s" % (str(e[0]), str(e[1]))
				s = g.node[e[0]]['set'].union(g.node[e[1]]['set'])			
				
				# insert into graph.
				g.add_node(n, {'set':s, 'graph':None})
				
				# rehook edges.
				for q in g.neighbors(e[0]):
					if q == e[1]: continue
					cut = g[e[0]][q]['cut']
					g.remove_edge(e[0], q)
					g.add_edge(n, q, {'cut':cut})

				for q in g.neighbors(e[1]):
					if q == e[0]: continue
					cut = g[e[1]][q]['cut']
					g.remove_edge(e[1], q)
					g.add_edge(n, q, {'cut':cut})		
					
				# do contraction.
				g.remove_edge(e[0], e[1])
				g.remove_node(e[0])
				g.remove_node(e[1])
					
				# break and reset.
				test = True
				break
				
			# check if there was no mod.
			if test == False:
				break				
		logging.info("one contracted: %i to %i" % (psz, len(g.nodes())))

		# choose root.
		root = g.nodes()[0]

		# solve bottom up.
		logging.info("solving one (bottom): %d" % len(s0))
		for p, q, kids in self._dfs_gen(g, root, order=False):
			
			# grab active set.
			s1 = g.node[p]['set']
			g1 = g.node[p]['graph']
			large = len(s1) > self._cutoff
			
			# if its the root just solve.
			if q == -1:
				
				# just solve (hope its not a 2-component).
				if large == False:		
					# solve normal.
					self._load(s1)
					sol, val = self._solve()
					self._clear()
				else:
					# solve 2 decomp.
					print "NOT WRITTEN"
					sys.exit()
				
				# save to root.
				g.node[p]['sol'] = sol
				g.node[p]['val'] = val
			
			else:
			
				# get cut.
				cut = g[p][q]['cut']
				
				# solve 2 combinations of orientations.
				logging.info("solving one: %d" % len(s1))
				for x in [0, 1]:
					
					# switch on solve.
					if large == False:
					
						# solve normal.
						self._load(s1)
						self._force(cut, x)
						sol, val = self._solve()
						self._clear()
						
					else:
												
						# solve decompose.
						sol, val = self._two(g1, s1, cut, x)
						
					# save info.
					g.node[p]['sol_%i' % x] = sol
					g.node[p]['val_%i' % x] = val
				
		# prepare a partial solution.
		nlist = build_nlist(self._nodes, s0)
		blist = build_blist(self._bundles, s0)
		tlist = build_tlist(self._bundles, s0)
		partial = PartialSolution(nlist.size, blist.size)
		val = 0.0
		
		# apply solution top down.
		logging.info("applying one (top): %d" % len(s0))
		for p, q, kids in self._dfs_gen(g, root, order=True):
			
			# grab active set.
			s1 = g.node[p]['set']
			
			# just apply root.
			if q == -1:
				partial.merge(g.node[p]['sol'])
				val += g.node[p]['val']
				continue
			
				
			# determine what the parent did.
			cut = g[p][q]['cut']
			o = partial.get_orien(cut)
				
			# apply that solution.
			partial.merge(g.node[p]['sol_%i' % o])
			val += g.node[p]['val_%i' % o]
			
		# return solution.
		return partial, val