Skip to content

Instantly share code, notes, and snippets.

@5tigerjelly
Created April 28, 2017 02:09
Show Gist options
  • Save 5tigerjelly/71d53f076f798dd1879454d2acfe821a to your computer and use it in GitHub Desktop.
Save 5tigerjelly/71d53f076f798dd1879454d2acfe821a to your computer and use it in GitHub Desktop.
'''Build_Sustainable.py
A QUIET Solving Tool problem formulation.
QUIET = Quetzal User Intelligence Enhancing Technology.
The XML-like tags used here serve to identify key sections of this
problem formulation.
CAPITALIZED constructs are generally present in any problem
formulation and therefore need to be spelled exactly the way they are.
Other globals begin with a capital letter but otherwise are lower
case or camel case.
'''
# <METADATA>
QUIET_VERSION = "0.2"
PROBLEM_NAME = "Designing buildings for Environmental Sustainability"
PROBLEM_VERSION = "0.2"
PROBLEM_AUTHORS = ['A. Krishnamoorthy', "Bum Mook Oh", "Ishan Saksena"]
PROBLEM_CREATION_DATE = "27-APR-2017"
PROBLEM_DESC = \
'''This formulation models sustainable building design uses generic
Python 3 constructs and has been tested with Python 3.4.
It is designed to work according to the QUIET tools interface, Version 0.2.
'''
# </METADATA>
# <COMMON_CODE>
def can_build(s, b_property, amount):
'''Tests whether we can change the construction factor'''
brickAmount = 0
if b_property == 'PeopleServed':
newCost = brickToPeople(s)
else:
newCost = COSTS[b_property]
try:
enough_budget = (s.d['budget'] >= newCost)
if (b_property in bricks(s)):
brickAmount = s.d['ConstructionMaterial'][b_property]
return enough_budget and (amount > 0 and amount + brickAmount > 0)
except (Exception) as e:
print(e)
def build(s, b_property, quantity):
'''Assuming it's legal to make the move, this computes
the new state resulting from moving the topmost disk
from the From peg to the To peg.'''
new_state = s.__copy__() # start with a deep copy.
d2 = new_state.d # grab the new state's dictionary.
if (b_property in bricks(s)):
d2['ConstructionMaterial'][b_property] += quantity
if b_property == 'PeopleServed':
d2['budget'] -= brickToPeople(s)
else:
d2['budget'] -= COSTS[b_property]
return new_state # return new state
def goal_test(s):
'''If the first two pegs are empty, then s is a goal state.'''
return not s.d['budget']
def goal_message(s):
return "Our building is pretty sustainable"
class Operator:
def __init__(self, name, precond, state_transf):
self.name = name
self.precond = precond
self.state_transf = state_transf
def is_applicable(self, s):
return self.precond(s)
def apply(self, s):
return self.state_transf(s)
# </COMMON_CODE>
# <COMMON_DATA>
# </COMMON_DATA>
# <STATE>
class State():
def __init__(self, d):
self.d = d
def __str__(self):
# Produces a brief textual description of a state.
d = self.d
txt = "["
for k in d.keys():
if k == 'ConstructionMaterial':
for brick in self.d[k].keys():
txt += brick + ': ' + str(self.d[k][brick])
txt += ", "
else:
txt += str(k) + ': ' + str(d[k])
txt += ", "
return txt[:-2] + "]"
def __eq__(self, s2):
if not (type(self) == type(s2)): return False
d1 = self.d
d2 = s2.d
for k in d1['ConstructionMaterial'].keys():
if d1['ConstructionMaterial'][k] != d2['ConstructionMaterial'][k]:
return False
return (d1['NumberOfPlants'] == d2['NumberOfPlants']) and (d1['PeopleServed'] == d2['PeopleServed'])
def __hash__(self):
return (str(self)).__hash__()
def __copy__(self):
# Performs an appropriately deep copy of a state,
# for use by operators in creating new states.
news = State({})
self.d
for k in self.d.keys():
if k == 'ConstructionMaterial':
for brick in self.d[k]:
if 'ConstructionMaterial' not in news.d:
news.d['ConstructionMaterial'] = {}
# print(self.d)
# print()
# print()
news.d['ConstructionMaterial'][brick] = self.d['ConstructionMaterial'][brick]
else:
news.d[k] = self.d[k]
return news
# </STATE>
# <INITIAL_STATE>
COSTS = {"Red Brick": 40, "Ash Brick": 30, "Concrete": 20, 'NumberOfPlants': 5}
bricks = lambda s : (s.d["ConstructionMaterial"].keys())
brickToPeople = lambda s: sum([s.d["ConstructionMaterial"][key] for key in s.d["ConstructionMaterial"].keys()]) / 20
brickSum = lambda s: sum([s.d["ConstructionMaterial"][key] for key in s.d["ConstructionMaterial"].keys()])
INITIAL_STATE = State(
{'ConstructionMaterial': {'Red Brick': 0, 'Ash Brick': 0, 'Concrete': 0}, 'EmissionPenalty': 0, 'NumberOfPlants': 0,
'PeopleServed': 0, 'cost': 0, 'budget': 10000})
CREATE_INITIAL_STATE = lambda: INITIAL_STATE
# </INITIAL_STATE>
# <OPERATORS>
build_combinations = [('Red Brick', 1000), ('Red Brick', -1000), ('Ash Brick', 1000),
('Ash Brick', -1000), ('Concrete', 1000), ('Concrete', -1000), ('NumberOfPlants', 5),
('NumberOfPlants', -5), ('PeopleServed', 10), ('PeopleServed', -10)]
OPERATORS = [Operator("Change " + str(b_property) + " by " + str(amount),
lambda s, b_property1=b_property, amount1=amount: can_build(s, b_property1, amount1),
# The default value construct is needed
# here to capture the values of p&q separately
# in each iteration of the list comp. iteration.
lambda s, b_property1=b_property, amount1=amount: build(s, b_property1, amount1))
for (b_property, amount) in build_combinations]
# </OPERATORS>
# <GOAL_TEST>
GOAL_TEST = lambda s: goal_test(s)
# </GOAL_TEST>
# <GOAL_MESSAGE_FUNCTION>
GOAL_MESSAGE_FUNCTION = lambda s: goal_message(s)
# </GOAL_MESSAGE_FUNCTION>
# <HEURISTICS> (optional)
def heuristic1(s):
d = s.d
return d["PeopleServed"] + d["NumberOfPlants"] - brickSum(s) - d["EmissionPenalty"]
HEURISTICS = {'heuristic1': heuristic1}
# </HEURISTICS>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment