Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angelic_search #940

Merged
merged 8 commits into from Jul 22, 2018
177 changes: 168 additions & 9 deletions tests/test_planning.py
Expand Up @@ -283,17 +283,176 @@ def test_job_shop_problem():

def test_refinements():

library = {'HLA': ['Go(Home,SFO)','Taxi(Home, SFO)'],
'steps': [['Taxi(Home, SFO)'],[]],
'precond': [['At(Home)'],['At(Home)']],
'effect': [['At(SFO)'],['At(SFO)'],['~At(Home)'],['~At(Home)']]}
library = {
'HLA': ['Go(Home,SFO)', 'Go(Home,SFO)', 'Drive(Home, SFOLongTermParking)', 'Shuttle(SFOLongTermParking, SFO)', 'Taxi(Home, SFO)'],
'steps': [['Drive(Home, SFOLongTermParking)', 'Shuttle(SFOLongTermParking, SFO)'], ['Taxi(Home, SFO)'], [], [], []],
'precond': [['At(Home)', 'Have(Car)'], ['At(Home)'], ['At(Home)', 'Have(Car)'], ['At(SFOLongTermParking)'], ['At(Home)']],
'effect': [['At(SFO)'], ['At(SFO)'], ['At(SFOLongTermParking)'], ['At(SFO)'], ['At(SFO)'], ['~At(Home)'], ['~At(Home)'], ['~At(Home)'], ['~At(SFOLongTermParking)'], ['~At(Home)']] }


go_SFO = HLA('Go(Home,SFO)', precond='At(Home)', effect='At(SFO) & ~At(Home)')
taxi_SFO = HLA('Go(Home,SFO)', precond='At(Home)', effect='At(SFO) & ~At(Home)')
taxi_SFO = HLA('Taxi(Home,SFO)', precond='At(Home)', effect='At(SFO) & ~At(Home)')

prob = Problem('At(Home)', 'At(SFO)', [go_SFO, taxi_SFO])
prob = Problem('At(Home) & Have(Car)', 'At(SFO)', [go_SFO, taxi_SFO])

result = [i for i in Problem.refinements(go_SFO, prob, library)]
assert(len(result) == 1)
assert(result[0].name == 'Taxi')
assert(result[0].args == (expr('Home'), expr('SFO')))

for sequence in Problem.refinements(go_SFO, prob, library):
print ('ref',[(s.name, s.args) for s in sequence])

assert(len(result) == 2)
assert(result[0][0].name == 'Drive')
assert(result[0][0].args == (expr('Home'), expr('SFOLongTermParking')))
assert(result[0][1].name == 'Shuttle')
assert(result[0][1].args == (expr('SFOLongTermParking'), expr('SFO')))
assert(result[1][0].name == 'Taxi')
assert(result[1][0].args == expr('Home'), expr('SFO'))


def test_convert_angelic_HLA():
"""
Converts angelic HLA's into expressions that correspond to their actions
~ : Delete (Not)
$+ : Possibly add (PosYes)
$-: Possibly delete (PosNo)
$$: Possibly add / delete (PosYesNo)
"""
ang1 = Angelic_HLA('Test', precond = None, effect = '~A')
ang2 = Angelic_HLA('Test', precond = None, effect = '$+A')
ang3 = Angelic_HLA('Test', precond = None, effect = '$-A')
ang4 = Angelic_HLA('Test', precond = None, effect = '$$A')

assert(ang1.convert(ang1.effect) == [expr('NotA')])
assert(ang2.convert(ang2.effect) == [expr('PosYesA')])
assert(ang3.convert(ang3.effect) == [expr('PosNotA')])
assert(ang4.convert(ang4.effect) == [expr('PosYesNotA')])


def test_is_primitive():
"""
Tests if a plan is consisted out of primitive HLA's (angelic HLA's)
"""
library = {
'HLA': ['Go(Home,SFO)', 'Go(Home,SFO)', 'Drive(Home, SFOLongTermParking)', 'Shuttle(SFOLongTermParking, SFO)', 'Taxi(Home, SFO)'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since several test functions use this same library. Define the library once (as a global variable) at the beginining of the angelic_search tests and share that definition across the different tests.

'steps': [['Drive(Home, SFOLongTermParking)', 'Shuttle(SFOLongTermParking, SFO)'], ['Taxi(Home, SFO)'], [], [], []],
'precond': [['At(Home)', 'Have(Car)'], ['At(Home)'], ['At(Home)', 'Have(Car)'], ['At(SFOLongTermParking)'], ['At(Home)']],
'effect': [['At(SFO)'], ['At(SFO)'], ['At(SFOLongTermParking)'], ['At(SFO)'], ['At(SFO)'], ['~At(Home)'], ['~At(Home)'], ['~At(Home)'], ['~At(SFOLongTermParking)'], ['~At(Home)']] }

angelic_opt_description = Angelic_HLA('Go(Home, SFO)', precond = 'At(Home)', effect ='$+At(SFO) & $-At(Home)' )
angelic_pes_description = Angelic_HLA('Go(Home, SFO)', precond = 'At(Home)', effect ='$+At(SFO) & ~At(Home)' )
taxi_SFO = HLA('Taxi(Home, SFO)', precond = 'At(Home)', effect = 'At(SFO)')
drive_SFOLongTermParking = HLA('Drive(Home,SFOLongTermParking)', precond='At(Home) & Car', effect='At(SFOLongTermParking) & ~At(Home)')
shuttle_SFO = HLA('Shuttle(SFOLongTermParking,SFO)', precond = 'At(SFOLongTermParking)', effect = 'At(SFO) & ~At(SFOLongTermParking)')

plan1 = Angelic_Node('At(Home)', None, [angelic_opt_description], [angelic_pes_description])
plan2 = Angelic_Node('At(Home)', None, [taxi_SFO])
plan3 = Angelic_Node('At(Home)', None, [drive_SFOLongTermParking, shuttle_SFO])

assert(not Problem.is_primitive(plan1, library))
assert(Problem.is_primitive(plan2, library))

assert(Problem.is_primitive(plan3, library))


def test_angelic_action():
"""
Finds the HLA actions that correspond to the HLA actions with angelic semantics

h1 : precondition positive: B _______ (add A) or (add A and remove B)
effect: add A and possibly remove B

h2 : precondition positive: A _______ (add A and add C) or (delete A and add C) or (add C) or (add A and delete C) or
effect: possibly add/remove A and possibly add/remove C (delete A and delete C) or (delete C) or (add A) or (delete A) or []

"""
h_1 = Angelic_HLA( expr('h1'), 'B' , 'A & $-B')
h_2 = Angelic_HLA( expr('h2'), 'A', '$$A & $$C')
action_1 = Angelic_HLA.angelic_action(h_1)
action_2 = Angelic_HLA.angelic_action(h_2)

assert ([a.effect for a in action_1] == [ [expr('A'),expr('NotB')], [expr('A')]] )
assert ([a.effect for a in action_2] == [[expr('A') , expr('C')], [expr('NotA'), expr('C')], [expr('C')], [expr('A'), expr('NotC')], [expr('NotA'), expr('NotC')], [expr('NotC')], [expr('A')], [expr('NotA')], [None] ] )


def test_optimistic_reachable_set():

h_1 = Angelic_HLA( 'h1', 'B' , '$+A & $-B ')
h_2 = Angelic_HLA( 'h2', 'A', '$$A & $$C')
f_1 = HLA('h1', 'B', 'A & ~B')
f_2 = HLA('h2', 'A', 'A & C')
problem = Problem('B', 'A', [f_1,f_2] )
plan = Angelic_Node(problem.init, None, [h_1,h_2], [h_1,h_2])
opt_reachable_set = Problem.reach_opt(problem.init, plan )
assert(opt_reachable_set[1] == [[expr('A'), expr('NotB')], [expr('NotB')],[expr('B'), expr('A')], [expr('B')]])
assert( problem.intersects_goal(opt_reachable_set) )


def test_pesssimistic_reachable_set():
"""
Given a problem initial state and a plan
"""
h_1 = Angelic_HLA( 'h1', 'B' , '$+A & $-B ')
h_2 = Angelic_HLA( 'h2', 'A', '$$A & $$C')
f_1 = HLA('h1', 'B', 'A & ~B')
f_2 = HLA('h2', 'A', 'A & C')
problem = Problem('B', 'A', [f_1,f_2] )
plan = Angelic_Node(problem.init, None, [h_1,h_2], [h_1,h_2])
pes_reachable_set = Problem.reach_pes(problem.init, plan )
assert(pes_reachable_set[1] == [[expr('A'), expr('NotB')], [expr('NotB')],[expr('B'), expr('A')], [expr('B')]])
assert(problem.intersects_goal(pes_reachable_set))


def test_find_reachable_set():
h_1 = Angelic_HLA( 'h1', 'B' , '$+A & $-B ')
f_1 = HLA('h1', 'B', 'A & ~B')
problem = Problem('B', 'A', [f_1] )
plan = Angelic_Node(problem.init, None, [h_1], [h_1])
reachable_set = {0: [problem.init]}
action_description = [h_1]

reachable_set = Problem.find_reachable_set(reachable_set, action_description)
assert(reachable_set[1] == [[expr('A'), expr('NotB')], [expr('NotB')],[expr('B'), expr('A')], [expr('B')]])



def test_intersects_goal():
problem_1 = Problem('At(SFO)', 'At(SFO)', [])
problem_2 = Problem('At(Home) & Have(Cash) & Have(Car) ', 'At(SFO) & Have(Cash)', [])
reachable_set_1 = {0: [problem_1.init]}
reachable_set_2 = {0: [problem_2.init]}

assert(Problem.intersects_goal(problem_1, reachable_set_1))
assert(not Problem.intersects_goal(problem_2, reachable_set_2))


def test_making_progress():
"""
function not yet implemented
"""
assert(True)

def test_angelic_search():

library = {
'HLA': ['Go(Home,SFO)', 'Go(Home,SFO)', 'Drive(Home, SFOLongTermParking)', 'Shuttle(SFOLongTermParking, SFO)', 'Taxi(Home, SFO)'],
'steps': [['Drive(Home, SFOLongTermParking)' , 'Shuttle(SFOLongTermParking, SFO)'], ['Taxi(Home, SFO)'], [], [], []],
'precond': [['At(Home)', 'Have(Car)'], ['At(Home)'], ['At(Home)', 'Have(Car)'], ['At(SFOLongTermParking)'], ['At(Home)']],
'effect': [['At(SFO)'], ['At(SFO)'], ['At(SFOLongTermParking)'], ['At(SFO)'], ['At(SFO)'], ['~At(Home)'], ['~At(Home)'], ['~At(Home)'], ['~At(SFOLongTermParking)'], ['~At(Home)']]
}

go_SFO = HLA('Go(Home,SFO)', precond='At(Home)', effect='At(SFO) & ~At(Home)')
taxi_SFO = HLA('Taxi(Home,SFO)', precond='At(Home) & Cash', effect='At(SFO) & ~At(Home)')
drive_SFOLongTermParking = HLA('Drive(Home,SFOLongTermParking)', precond='At(Home) & Car', effect='At(SFOLongTermParking) & ~At(Home)')
shuttle_SFO = HLA('Shuttle(SFOLongTermParking,SFO)', precond = 'At(SFOLongTermParking)', effect = 'At(SFO) & ~At(SFOLongTermParking)')

prob = Problem('At(Home) & Have(Cash) & Have(Car) ', 'At(SFO) & Have(Cash)', [go_SFO, taxi_SFO, drive_SFOLongTermParking,shuttle_SFO])

angelic_opt_description = Angelic_HLA('Go(Home, SFO)', precond = 'At(Home)', effect ='$+At(SFO) & $-At(Home)' )
angelic_pes_description = Angelic_HLA('Go(Home, SFO)', precond = 'At(Home)', effect ='$+At(SFO) & ~At(Home)' )


initialPlan = [Angelic_Node(prob.init, None, [angelic_opt_description], [angelic_pes_description])]
assert( Problem.angelic_search(prob, library, initialPlan) )