Skip to content

Commit

Permalink
hw4 and simulated annealing
Browse files Browse the repository at this point in the history
  • Loading branch information
William Farmer committed Sep 23, 2016
1 parent 90e3275 commit 4557849
Show file tree
Hide file tree
Showing 13 changed files with 2,416 additions and 0 deletions.
Binary file added hw3/willfarmerhw3.zip
Binary file not shown.
379 changes: 379 additions & 0 deletions hw4/.ipynb_checkpoints/Will Farmer - Homework 4-checkpoint.ipynb

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions hw4/Will Farmer - Homework 4.aux
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
\relax
\providecommand\hyper@newdestlabel[2]{}
\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument}
\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined
\global\let\oldcontentsline\contentsline
\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}}
\global\let\oldnewlabel\newlabel
\gdef\newlabel#1#2{\newlabelxx{#1}#2}
\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}}
\AtEndDocument{\ifx\hyper@anchor\@undefined
\let\contentsline\oldcontentsline
\let\newlabel\oldnewlabel
\fi}
\fi}
\global\let\hyper@last\relax
\gdef\HyperFirstAtBeginDocument#1{#1}
\providecommand\HyField@AuxAddToFields[1]{}
\providecommand\HyField@AuxAddToCoFields[2]{}
\providecommand \oddpage@label [2]{}
\@writefile{toc}{\contentsline {section}{\numberline {1}Problem 1}{1}{section.1}}
\newlabel{problem-1}{{1}{1}{Problem 1}{section.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {2}Problem 2}{4}{section.2}}
\newlabel{problem-2}{{2}{4}{Problem 2}{section.2}{}}
\@writefile{toc}{\contentsline {section}{\numberline {3}Problem 3}{4}{section.3}}
\newlabel{problem-3}{{3}{4}{Problem 3}{section.3}{}}
379 changes: 379 additions & 0 deletions hw4/Will Farmer - Homework 4.ipynb

Large diffs are not rendered by default.

774 changes: 774 additions & 0 deletions hw4/Will Farmer - Homework 4.log

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions hw4/Will Farmer - Homework 4.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
\BOOKMARK [1][-]{section.1}{Problem 1}{}% 1
\BOOKMARK [1][-]{section.2}{Problem 2}{}% 2
\BOOKMARK [1][-]{section.3}{Problem 3}{}% 3
571 changes: 571 additions & 0 deletions hw4/Will Farmer - Homework 4.tex

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added hw4/hw4.xoj
Binary file not shown.
Binary file added hw4/tree.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added hw4/tree1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
285 changes: 285 additions & 0 deletions inclass/will_farmer_20160923.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
#!/usr/bin/env python3.5

import sys
import argparse
import re

import math

import random
import time


###############################################################
# From homework 3
###############################################################
class Node(object):
def __init__(self, name, weight=1):
self.name = name
self.weight = weight
self.edges = []

@property
def neighbors(self):
return [e.end.name for e in self.edges]

def get_edge_weight(self, end):
weight = None
for edge in self.edges:
if edge.end.name == end:
weight = edge.weight
if weight is None:
raise EdgeException('Edge does not exist!')
else:
return weight


class Edge(object):
def __init__(self, start, end, weight=1):
self.start = start
self.end = end
self.weight = weight


class Graph(object):
"""
Directed graph with weighted edges (default weight of 1)
Stored as adjacency list
Nodes can be classes but int(node) needs to return a number
"""
def __init__(self):
self.graph = {}
self.c = 5
self.infinity = 1e8
self.inf = self.infinity
self.q = BMinHeap()

def __getitem__(self, key):
try:
return self.graph[key]
except KeyError:
raise NodeException("Node does not exist")

@property
def size(self):
return len(self.graph.keys())

@property
def nodes(self):
return list(self.graph.keys())

@property
def edges(self):
return list([(k, v) for k, v in self.graph.items()])

def generate_erdosrenyi(self, node_total, c=5):
""" Generate random graph """
self.c = c
p = c / (node_total - 1)
letter = 96
for n in range(node_total):
self.add_node(chr(letter + n))
for start in self.graph.keys():
for end in self.graph.keys():
if start[0] != end[0]:
if random.random() < p:
self.add_edge(start[0], end[0])

def to_networkx(self):
G = nx.DiGraph()
for node in self.nodes:
G.add_node(node)
for node in self.nodes:
for edge in self.graph[node].edges:
G.add_edge(node, edge.end.name, weight=edge.weight)
return G

def plot(self):
g = self.to_networkx()
plt.figure()
layout = nx.spectral_layout(g, weight=None, scale=5)
nx.draw_networkx(g, layout)
plt.axis('off')
plt.savefig('./graph.png')

def add_node(self, name):
try:
self.graph[name]
raise NodeException('Node Already Exists!')
except KeyError:
node = Node(name)
self.graph[node.name] = node

def add_edge(self, start, end, weight=1):
""" adds edge (and node if not exist) """
for val in [start, end]:
try:
self.graph[val]
except KeyError:
node = Node(val)
self.graph[val] = node
edge = Edge(self.graph[start], self.graph[end], weight=weight)
self.graph[start].edges.append(edge)

def find_adjacent(self, name):
"""
Return adjacent nodes
"""
try:
return self.graph[name].edges
except KeyError:
raise NodeException('Node Does not Exist!')

def to_edge_list(self):
"""
Return an edge list representation of graph
"""
edges = []
for name, cls in self.graph.items():
for e in cls.edges:
edges.append((name, e.end.name))
return sorted(edges, key=lambda tup: tup[0])


class BMinHeap:
"""
Priority Queue (Min-Heap)
"""
def __init__(self):
self.queue = [] # Defined queue
self.infinity = 1e8

def adjust(self, name, val):
for n in range(len(self.queue)):
if self.queue[n][0] == name:
new = (self.queue[n][0], val)
self.queue.pop(n)
self.push(new)
break
self.__min_heapify__(0)

def push(self, num):
"""
Insert new node into min-heap
"""
self.queue.append(num) # Add to lowest level
for i in range(len(self.queue) - 1, -1, -1): # Iterate through children to parents
child = self.queue[i]
parent = self.queue[int((i - 1) / 2)]
if child[1] < parent[1]:
self.__swap__(i, int((i - 1) / 2)) # Swap the two

def __swap__(self, i, j):
self.queue[i], self.queue[j] = self.queue[j], self.queue[i]

def find_min(self):
if len(self.queue) == 0:
return None
heapmin = self.queue.pop(0) # It will always be the first
if len(self.queue) > 0:
self.queue.insert(0, self.queue.pop(len(self.queue) - 1))
self.__min_heapify__(0) # Re-order tree
return heapmin

def __min_heapify__(self, i):
parent = i # Current number
left = 2 * i + 1 # Left child
right = 2 * i + 2 # Right Child
if (left < len(self.queue) and
self.queue[left][1] < self.queue[parent][1]):
parent = left
if (right < len(self.queue) and
self.queue[right][1] < self.queue[parent][1]):
parent = right
if parent != i: # If smallest changed, adjust
self.__swap__(i, parent)
self.__min_heapify__(parent)


class EdgeException(Exception):
def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)


class NodeException(Exception):
def __init__(self, value):
self.value = value

def __str__(self):
return repr(self.value)
###############################################################
# End from homework 3
###############################################################

g = Graph()
g.add_edge('A', 'B', weight=185)
g.add_edge('B', 'A', weight=185)
g.add_edge('A', 'C', weight=119)
g.add_edge('C', 'A', weight=119)
g.add_edge('A', 'D', weight=152)
g.add_edge('D', 'A', weight=152)
g.add_edge('A', 'E', weight=133)
g.add_edge('E', 'A', weight=133)
g.add_edge('B', 'C', weight=121)
g.add_edge('C', 'B', weight=121)
g.add_edge('B', 'D', weight=150)
g.add_edge('D', 'B', weight=150)
g.add_edge('B', 'E', weight=120)
g.add_edge('E', 'B', weight=120)
g.add_edge('C', 'D', weight=174)
g.add_edge('D', 'C', weight=174)
g.add_edge('C', 'E', weight=200)
g.add_edge('E', 'C', weight=200)
g.add_edge('D', 'E', weight=199)
g.add_edge('E', 'D', weight=199)

def generate_solution(g):
nodes = g.nodes
path = []
cost = 0
for i in range(len(nodes)):
choice = random.choice(nodes)
path.append(choice)
nodes.remove(choice)
if len(path) > 1:
cost += g[path[-2]].get_edge_weight(path[-1])
cost += g[path[-1]].get_edge_weight(path[0])
return path, cost

def generate_solution_neighbor(g, s, c):
flip = random.randint(0, len(s) - 2)
new_path = s
new_path[flip], new_path[flip + 1] = new_path[flip + 1], new_path[flip]
new_cost = 0
for i in range(len(s) - 1):
new_cost += g[new_path[i]].get_edge_weight(new_path[i + 1])
new_cost += g[new_path[-1]].get_edge_weight(new_path[0])
return new_path, new_cost

def simulated_annealing(g):
s, c = generate_solution(g)
T = 1
Tmin = 1e-9
alpha = 0.99
k = 1
i = 0
while T > Tmin:
sp, cp = generate_solution_neighbor(g, s, c)
DE = cp - c
# print(s, c, math.exp(-DE / (k * T)))
if DE < 0:
s = sp
c = cp
elif random.random() < math.exp(-DE / (k * T)):
s = sp
c = cp
T *= alpha
i += 1
print(s, c, i)

simulated_annealing(g)

0 comments on commit 4557849

Please sign in to comment.