sfplanner 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
- SFP Planner for Ruby
2
- ====================
1
+ SFPlanner
2
+ =========
3
3
  - Author: Herry (herry13@gmail.com)
4
4
  - [Version](https://github.com/herry13/sfplanner/blob/master/VERSION)
5
5
  - License: [BSD](https://github.com/herry13/sfp-ruby/blob/master/LICENSE)
6
6
 
7
- A Ruby gem that provides a Ruby API to SFP planner that solves a planning task written in [SFP language](https://github.com/herry13/nuri/wiki/SFP-language).
7
+ [![Gem Version](https://badge.fury.io/rb/sfplanner.png)](http://badge.fury.io/rb/sfplanner)
8
+
9
+ A Ruby script and library of SFP planner, which solves a planning task written in [SFP language](https://github.com/herry13/nuri/wiki/SFP-language).
8
10
 
9
11
  Click [here](https://github.com/herry13/nuri/wiki/SFP-language), for more details about SFP language.
10
12
 
@@ -22,13 +24,11 @@ Requirements
22
24
  - Ruby (>= 1.8.7)
23
25
  - Rubygems
24
26
  - sfp (>= 0.3.0)
25
- - antlr3
26
- - json
27
27
 
28
28
  Tested on:
29
29
  - Ubuntu 12.04
30
30
  - Debian Squeeze
31
- - Scientific Linux 6.
31
+ - Scientific Linux 6
32
32
  - MacOS X 10.8
33
33
 
34
34
 
@@ -43,53 +43,59 @@ To use as Ruby library
43
43
  ----------------------
44
44
  - parse an SFP file, and then generate the plan (if found) in Hash:
45
45
 
46
- # include sfplanner library
47
- require 'sfplanner'
46
+ ```ruby
47
+ # include sfplanner library
48
+ require 'sfplanner'
48
49
 
49
- # solve and return the plan in Hash
50
- planner.solve({:file => file_path})
50
+ # solve and return the plan in Hash
51
+ planner.solve({:file => file_path})
52
+ ```
51
53
 
52
54
  - parse an SFP file, and then generate the plan in JSON:
53
55
 
54
- # include sfplanner library
55
- require 'sfplanner'
56
+ ```ruby
57
+ # include sfplanner library
58
+ require 'sfplanner'
56
59
 
57
- # solve and return the plan in JSON
58
- planner.solve({:file => file_path, :json => true})
60
+ # solve and return the plan in Hash
61
+ planner.solve({:file => file_path, :json => true})
62
+ ```
59
63
 
60
64
 
61
65
  Example of Planning Task
62
66
  ------------------------
63
67
  - Create file **types.sfp** to hold required schemas:
64
68
 
65
- schema Service {
66
- running is false
67
- procedure start {
68
- conditions {
69
- this.running is false
70
- }
71
- effects {
72
- this.running is true
73
- }
69
+ ```javascript
70
+ schema Service {
71
+ running is false
72
+ procedure start {
73
+ conditions {
74
+ this.running is false
74
75
  }
75
- procedure stop {
76
- conditions {
77
- this.running is true
78
- }
79
- effects {
80
- this.running is false
81
- }
76
+ effects {
77
+ this.running is true
82
78
  }
83
79
  }
84
- schema Client {
85
- refer isref Service
86
- procedure redirect(s isref Service) {
87
- conditions { }
88
- effects {
89
- this.refer is s
90
- }
80
+ procedure stop {
81
+ conditions {
82
+ this.running is true
83
+ }
84
+ effects {
85
+ this.running is false
91
86
  }
92
87
  }
88
+ }
89
+ schema Client {
90
+ refer isref Service
91
+ procedure redirect(s isref Service) {
92
+ conditions { }
93
+ effects {
94
+ this.refer is s
95
+ }
96
+ }
97
+ }
98
+ ```
93
99
 
94
100
  In this file, we have two schemas that model our domain. First, schema
95
101
  **Service** with an attribute **running**, procedure **start** that
@@ -103,28 +109,30 @@ Example of Planning Task
103
109
 
104
110
  - Create file **task.sfp** to hold the task:
105
111
 
106
- include "types.sfp"
107
-
108
- initial state {
109
- a isa Service {
110
- running is true
111
- }
112
+ ```javascript
113
+ include "types.sfp"
114
+
115
+ initial state {
116
+ a isa Service {
117
+ running is true
118
+ }
112
119
 
113
- b isa Service // with "running" is false
120
+ b isa Service // with "running" is false
114
121
 
115
- pc isa Client {
116
- refer is a
117
- }
122
+ pc isa Client {
123
+ refer is a
118
124
  }
125
+ }
119
126
 
120
- goal constraint {
121
- pc.refer is b
122
- a.running is false
123
- }
127
+ goal constraint {
128
+ pc.refer is b
129
+ a.running is false
130
+ }
124
131
 
125
- global constraint {
126
- pc.refer.running is true
127
- }
132
+ global constraint {
133
+ pc.refer.running is true
134
+ }
135
+ ```
128
136
 
129
137
  In this file, we specify a task where in the initial state of our domain,
130
138
  we have two services **a** and **b**, and a client **pc**. **a** is
@@ -140,46 +148,48 @@ Example of Planning Task
140
148
 
141
149
  Which will generate a workflow in JSON
142
150
 
143
- {
144
- "type": "sequential",
145
- "workflow": [
146
- {
147
- "name": "$.b.start",
148
- "parameters": {
149
- },
150
- "condition": {
151
- "$.b.running": false
152
- },
153
- "effect": {
154
- "$.b.running": true
155
- }
156
- },
157
- {
158
- "name": "$.pc.redirect",
159
- "parameters": {
160
- "$.s": "$.b"
161
- },
162
- "condition": {
163
- },
164
- "effect": {
165
- "$.pc.refer": "$.b"
166
- }
167
- },
168
- {
169
- "name": "$.a.stop",
170
- "parameters": {
171
- },
172
- "condition": {
173
- "$.a.running": true
174
- },
175
- "effect": {
176
- "$.a.running": false
177
- }
178
- }
179
- ],
180
- "version": "1",
181
- "total": 3
182
- }
151
+ ```javascript
152
+ {
153
+ "type": "sequential",
154
+ "workflow": [
155
+ {
156
+ "name": "$.b.start",
157
+ "parameters": {
158
+ },
159
+ "condition": {
160
+ "$.b.running": false
161
+ },
162
+ "effect": {
163
+ "$.b.running": true
164
+ }
165
+ },
166
+ {
167
+ "name": "$.pc.redirect",
168
+ "parameters": {
169
+ "$.s": "$.b"
170
+ },
171
+ "condition": {
172
+ },
173
+ "effect": {
174
+ "$.pc.refer": "$.b"
175
+ }
176
+ },
177
+ {
178
+ "name": "$.a.stop",
179
+ "parameters": {
180
+ },
181
+ "condition": {
182
+ "$.a.running": true
183
+ },
184
+ "effect": {
185
+ "$.a.running": false
186
+ }
187
+ }
188
+ ],
189
+ "version": "1",
190
+ "total": 3
191
+ }
192
+ ```
183
193
 
184
194
  This workflow is sequential that has 3 procedures. If you executes
185
195
  the workflow in given order, it will achieves the goal state as well
@@ -189,16 +199,18 @@ Example of Planning Task
189
199
  Planner Options
190
200
  ---------------
191
201
  You could set particular environment variable to change the planner settings:
192
- - to activate debug-mode
202
+ - To activate debug-mode
193
203
 
194
- SFPLANNER_DEBUG=1
204
+ $ export SFPLANNER_DEBUG=1
205
+
206
+ This will disable automated deletion of temporary files in temporary directory (/tmp/nuri_****/).
195
207
 
196
- - to use multiple heuristic on finding the solution, and then pick the best result
208
+ - To use multiple heuristic on finding the solution, and then pick the best result
197
209
 
198
- SFPLANNER_MIXED_CONTINUE=1
210
+ $ export SFPLANNER_MIXED_CONTINUE=1
199
211
 
200
- - to set heuristics which are used in searching
212
+ - To set heuristics which are used in searching
201
213
 
202
- SFPLANNER_MIXED_HEURISTICS=ff2,cea2
214
+ $ export SFPLANNER_MIXED_HEURISTICS=ff2,cea2
203
215
 
204
216
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
@@ -39,6 +39,7 @@ module Sfp
39
39
  # if false or nil then return a sequential plan
40
40
  # @param :json : if true then return the plan in JSON
41
41
  # @param :pretty_json : if true then return in pretty JSON
42
+ # @param :bsig : if true then return the solution plan as a BSig model
42
43
  #
43
44
  def solve(params={})
44
45
  if params[:string].is_a?(String)
@@ -75,6 +76,7 @@ module Sfp
75
76
  raise Exception, "Conformant task is not supported yet" if @parser.conformant
76
77
 
77
78
  bsig = (params[:parallel] ? self.to_parallel_bsig : self.to_sequential_bsig)
79
+
78
80
  return (params[:json] ? JSON.generate(bsig) :
79
81
  (params[:pretty_json] ? JSON.pretty_generate(bsig) : bsig))
80
82
  end
@@ -107,7 +109,8 @@ module Sfp
107
109
  end
108
110
 
109
111
  def solve_conformant_task(params={})
110
- # TODO
112
+ raise Exception, "Conformant task is not supported yet" if params[:bsig]
113
+
111
114
  # 1) generate all possible initial states
112
115
  # remove states that do not satisfy the global constraint
113
116
  def get_possible_partial_initial_states(init)
@@ -171,49 +174,74 @@ module Sfp
171
174
 
172
175
  return @plan if params[:sas_plan]
173
176
 
177
+ return to_bsig(params) if params[:bsig]
178
+
174
179
  plan = (params[:parallel] ? self.get_parallel_plan : self.get_sequential_plan)
175
180
  return (params[:json] ? JSON.generate(plan) :
176
181
  (params[:pretty_json] ? JSON.pretty_generate(plan) : plan))
177
182
  end
178
183
 
179
184
  def bsig_template
180
- return {'version' => 1, 'operators' => [], 'id' => Time.now.getutc.to_i, 'goal' => []}
185
+ return {'version' => 1, 'operators' => [], 'id' => Time.now.getutc.to_i, 'goal' => {}, 'goal_operator' => {}}
181
186
  end
182
187
 
183
188
  def to_sequential_bsig
184
189
  bsig = self.bsig_template
185
190
  return bsig if @plan.length <= 0
191
+
186
192
  plan = self.get_sequential_plan
187
193
  bsig['operators'] = workflow = plan['workflow']
194
+
188
195
  (workflow.length-1).downto(1) do |i|
189
196
  op = workflow[i]
190
197
  prev_op = workflow[i-1]
191
198
  prev_op['effect'].each { |k,v| op['condition'][k] = v }
192
199
  end
193
200
  bsig['goal'], _ = self.bsig_goal_operator(workflow)
201
+
194
202
  return bsig
195
203
  end
196
204
 
197
205
  def to_parallel_bsig
206
+ def set_priority_index(operator, operators)
207
+ pi = 1
208
+ operator['successors'].each { |i|
209
+ set_priority_index(operators[i], operators)
210
+ pi = operators[i]['pi'] + 1 if pi <= operators[i]['pi']
211
+ }
212
+ operator['pi'] = pi
213
+ end
214
+
198
215
  return nil if @plan.nil?
216
+
199
217
  bsig = self.bsig_template
200
218
  return bsig if @plan.length <= 0
219
+
220
+ # generate parallel plan
201
221
  plan = self.get_parallel_plan
202
- # foreach operator's predecessors, add its effects to operator's conditions
203
- bsig['operators'] = workflow = plan['workflow']
204
- workflow.each do |op|
222
+
223
+ # set BSig operators
224
+ bsig['operators'] = operators = plan['workflow']
225
+
226
+ # set priority index
227
+ operators.each { |op| set_priority_index(op, operators) if op['predecessors'].length <= 0 }
228
+
229
+ # foreach operator
230
+ # - for each operator's predecessors, add its effects to operator's conditions
231
+ # - remove unnecessary data
232
+ operators.each do |op|
205
233
  op['predecessors'].each do |pred|
206
- pred_op = workflow[pred]
234
+ pred_op = operators[pred]
207
235
  pred_op['effect'].each { |k,v| op['condition'][k] = v }
208
236
  end
209
- end
210
- # remove unnecessary information
211
- workflow.each do |op|
212
237
  op.delete('id')
213
238
  op.delete('predecessors')
214
239
  op.delete('successors')
215
240
  end
216
- bsig['goal'], bsig['goal_operator'] = self.bsig_goal_operator(workflow)
241
+
242
+ # set goals
243
+ bsig['goal'], bsig['goal_operator'] = self.bsig_goal_operator(operators)
244
+
217
245
  return bsig
218
246
  end
219
247
 
@@ -255,7 +283,13 @@ module Sfp
255
283
 
256
284
  def get_parallel_plan
257
285
  json = {'type'=>'parallel', 'workflow'=>nil, 'init'=>nil, 'version'=>'1', 'total'=>0}
258
- return json if @plan == nil
286
+ if @plan.nil?
287
+ return json
288
+ elsif @plan.length <= 0
289
+ json['workflow'] = []
290
+ return json
291
+ end
292
+
259
293
  json['workflow'], json['init'], json['total'] = @sas_task.get_partial_order_workflow(@parser)
260
294
  return json
261
295
  end
data/lib/sfplanner/sas.rb CHANGED
@@ -99,7 +99,6 @@ module Nuri
99
99
  raise Exception, 'Cannot find operator: ' + op_name if operator.nil?
100
100
  op_sfw = operator.to_sfw
101
101
  op_sfw['id'] = i
102
- op_sfw['distance'] = distance
103
102
  op_sfw['successors'] = []
104
103
  op_sfw['predecessors'] = []
105
104
  sfw << op_sfw
@@ -116,6 +115,7 @@ module Nuri
116
115
  sfw[i]['predecessors'] << j
117
116
  end
118
117
  end
118
+
119
119
  return sfw, init, sfw.length
120
120
  end
121
121
 
data/sfplanner.gemspec CHANGED
@@ -16,5 +16,5 @@ Gem::Specification.new do |s|
16
16
  s.homepage = 'https://github.com/herry13/sfplanner'
17
17
  s.rubyforge_project = 'sfplanner'
18
18
 
19
- s.add_dependency 'sfp', '~> 0.3.11'
19
+ s.add_dependency 'sfp', '~> 0.3.12'
20
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sfplanner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,15 +13,15 @@ date: 2013-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sfp
16
- requirement: &8735620 !ruby/object:Gem::Requirement
16
+ requirement: &20029340 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.3.11
21
+ version: 0.3.12
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *8735620
24
+ version_requirements: *20029340
25
25
  description: A Ruby gem that provides a Ruby API and a script to the SFP planner.
26
26
  This planner can automatically generate a plan that solves a planning problem written
27
27
  in SFP language.