lib/sfplanner/planner.rb in sfplanner-0.1.2 vs lib/sfplanner/planner.rb in sfplanner-0.1.3
- old
+ new
@@ -37,10 +37,11 @@
# @param :sas_plan : if true then return a raw SAS plan
# @param :parallel : if true then return a parallel (partial-order) plan,
# if false or nil then return a sequential plan
# @param :json : if true then return the plan in JSON
# @param :pretty_json : if true then return in pretty JSON
+ # @param :bsig : if true then return the solution plan as a BSig model
#
def solve(params={})
if params[:string].is_a?(String)
@parser.parse(string)
elsif params[:sfp].is_a?(Hash)
@@ -73,10 +74,11 @@
#
def to_bsig(params={})
raise Exception, "Conformant task is not supported yet" if @parser.conformant
bsig = (params[:parallel] ? self.to_parallel_bsig : self.to_sequential_bsig)
+
return (params[:json] ? JSON.generate(bsig) :
(params[:pretty_json] ? JSON.pretty_generate(bsig) : bsig))
end
# @param :json : if true then return in JSON
@@ -105,11 +107,12 @@
sfp_task.accept(Sfp::Visitor::ParentEliminator.new)
File.open('/tmp/planning.json', 'w') { |f| f.write(JSON.pretty_generate(sfp_task)) }
end
def solve_conformant_task(params={})
- # TODO
+ raise Exception, "Conformant task is not supported yet" if params[:bsig]
+
# 1) generate all possible initial states
# remove states that do not satisfy the global constraint
def get_possible_partial_initial_states(init)
def combinators(variables, var_values, index=0, result={}, bucket=[])
if index >= variables.length
@@ -169,53 +172,78 @@
def solve_classical_task(params={})
@plan, @sas_task = self.solve_sas(@parser, params)
return @plan if params[:sas_plan]
+ return to_bsig(params) if params[:bsig]
+
plan = (params[:parallel] ? self.get_parallel_plan : self.get_sequential_plan)
return (params[:json] ? JSON.generate(plan) :
(params[:pretty_json] ? JSON.pretty_generate(plan) : plan))
end
def bsig_template
- return {'version' => 1, 'operators' => [], 'id' => Time.now.getutc.to_i, 'goal' => []}
+ return {'version' => 1, 'operators' => [], 'id' => Time.now.getutc.to_i, 'goal' => {}, 'goal_operator' => {}}
end
def to_sequential_bsig
bsig = self.bsig_template
return bsig if @plan.length <= 0
+
plan = self.get_sequential_plan
bsig['operators'] = workflow = plan['workflow']
+
(workflow.length-1).downto(1) do |i|
op = workflow[i]
prev_op = workflow[i-1]
prev_op['effect'].each { |k,v| op['condition'][k] = v }
end
bsig['goal'], _ = self.bsig_goal_operator(workflow)
+
return bsig
end
def to_parallel_bsig
+ def set_priority_index(operator, operators)
+ pi = 1
+ operator['successors'].each { |i|
+ set_priority_index(operators[i], operators)
+ pi = operators[i]['pi'] + 1 if pi <= operators[i]['pi']
+ }
+ operator['pi'] = pi
+ end
+
return nil if @plan.nil?
+
bsig = self.bsig_template
return bsig if @plan.length <= 0
+
+ # generate parallel plan
plan = self.get_parallel_plan
- # foreach operator's predecessors, add its effects to operator's conditions
- bsig['operators'] = workflow = plan['workflow']
- workflow.each do |op|
+
+ # set BSig operators
+ bsig['operators'] = operators = plan['workflow']
+
+ # set priority index
+ operators.each { |op| set_priority_index(op, operators) if op['predecessors'].length <= 0 }
+
+ # foreach operator
+ # - for each operator's predecessors, add its effects to operator's conditions
+ # - remove unnecessary data
+ operators.each do |op|
op['predecessors'].each do |pred|
- pred_op = workflow[pred]
+ pred_op = operators[pred]
pred_op['effect'].each { |k,v| op['condition'][k] = v }
end
- end
- # remove unnecessary information
- workflow.each do |op|
op.delete('id')
op.delete('predecessors')
op.delete('successors')
end
- bsig['goal'], bsig['goal_operator'] = self.bsig_goal_operator(workflow)
+
+ # set goals
+ bsig['goal'], bsig['goal_operator'] = self.bsig_goal_operator(operators)
+
return bsig
end
def bsig_goal_operator(workflow)
goal_op = {}
@@ -253,10 +281,16 @@
return json
end
def get_parallel_plan
json = {'type'=>'parallel', 'workflow'=>nil, 'init'=>nil, 'version'=>'1', 'total'=>0}
- return json if @plan == nil
+ if @plan.nil?
+ return json
+ elsif @plan.length <= 0
+ json['workflow'] = []
+ return json
+ end
+
json['workflow'], json['init'], json['total'] = @sas_task.get_partial_order_workflow(@parser)
return json
end
def extract_sas_plan(sas_plan, parser)