LightVoting
 All Classes Namespaces Files Functions Variables Pages
CChairAgent.java
Go to the documentation of this file.
1 
24 package org.lightvoting.simulation.agent;
25 
26 import cern.colt.bitvector.BitVector;
27 import org.lightjason.agentspeak.action.binding.IAgentAction;
28 import org.lightjason.agentspeak.action.binding.IAgentActionFilter;
29 import org.lightjason.agentspeak.action.binding.IAgentActionName;
30 import org.lightjason.agentspeak.agent.IBaseAgent;
31 import org.lightjason.agentspeak.common.CCommon;
32 import org.lightjason.agentspeak.configuration.IAgentConfiguration;
33 import org.lightjason.agentspeak.generator.IBaseAgentGenerator;
34 import org.lightjason.agentspeak.language.CLiteral;
35 import org.lightjason.agentspeak.language.CRawTerm;
36 import org.lightjason.agentspeak.language.ILiteral;
37 import org.lightjason.agentspeak.language.instantiable.plan.trigger.CTrigger;
38 import org.lightjason.agentspeak.language.instantiable.plan.trigger.ITrigger;
39 import org.lightjason.agentspeak.language.score.IAggregation;
43 
44 import java.io.InputStream;
45 import java.text.MessageFormat;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.LinkedList;
49 import java.util.List;
50 import java.util.concurrent.atomic.AtomicIntegerArray;
51 import java.util.concurrent.atomic.AtomicLong;
52 import java.util.concurrent.atomic.AtomicReference;
53 import java.util.stream.Collectors;
54 import java.util.stream.Stream;
55 
56 
61 // annotation to mark the class that actions are inside
62 @IAgentAction
63 public final class CChairAgent extends IBaseAgent<CChairAgent>
64 {
65 
69  private final String m_name;
70 
75  private final CEnvironment m_environment;
76  private List<CVotingAgent> m_agents;
77 
81  private String m_grouping;
82 
83  private int m_iteration;
84  private String m_protocol;
85  private List<Double> m_dissList;
86  private List<CVotingAgent> m_dissVoters;
87  private double m_dissThreshold = 1.1;
88  private boolean m_iterative;
89  private List<BitVector> m_bitVotes;
90  private final String m_fileName;
91 
101  public CChairAgent( final String p_name, final IAgentConfiguration<CChairAgent> p_configuration, final CEnvironment p_environment, final String p_grouping,
102  final String p_protocol,
103  final String p_fileName
104  )
105  {
106  super( p_configuration );
107  m_name = p_name;
108  m_environment = p_environment;
109  m_bitVotes = Collections.synchronizedList( new LinkedList<>() );
110  m_dissList = Collections.synchronizedList( new LinkedList<>() );
111  m_dissVoters = Collections.synchronizedList( new LinkedList<>() );
112  m_grouping = p_grouping;
113  m_protocol = p_protocol;
114  m_iteration = 0;
115  m_agents = Collections.synchronizedList( new LinkedList<>() );
116  m_iterative = false;
117  m_fileName = p_fileName;
118  }
119 
120  // overload agent-cycle
121  @Override
122  public final CChairAgent call() throws Exception
123  {
124  // run default cycle
125  return super.call();
126  }
127 
128  // public methods
129 
130  public String name()
131  {
132  return m_name;
133  }
134 
135  // agent actions
136 
140  @IAgentActionFilter
141  @IAgentActionName( name = "perceive/group" )
145  public void perceiveGroup()
146  {
147  if ( !( m_environment.detectGroup( this ) == null ) )
148  this.beliefbase().add( m_environment.detectGroup( this ) );
149  }
150 
154  @IAgentActionFilter
155  @IAgentActionName( name = "check/conditions" )
159  public void checkConditions()
160  {
161  final CGroup l_group = this.determineGroup();
162 
163  // if conditions for election are fulfilled, trigger goal start/criterion/fulfilled
164 
165  final ITrigger l_trigger;
166 
167  // if m_iterative is true, we have the case of iterative voting, i.e. we already have the votes
168  // we only need to repeat the computation of the result
169 
170  if ( m_iterative && ( l_group.readyForElection() && !( l_group.electionInProgress() ) ) )
171  {
172  m_iteration++;
173  this.computeResult();
174  return;
175  }
176 
177 
178  if ( l_group.readyForElection() && ( !( l_group.electionInProgress() ) ) )
179  {
180  l_group.startProgress();
181 
182  l_trigger = CTrigger.from(
183  ITrigger.EType.ADDGOAL,
184  CLiteral.from( "start/criterion/fulfilled" )
185  );
186 
187  this.trigger( l_trigger );
188  }
189  }
190 
191  // private methods
192 
194  {
195  final AtomicReference<CGroup> l_groupAtomic = new AtomicReference<>();
196  final Collection l_groups = this.beliefbase().beliefbase().literal( "group" );
197  l_groups.stream().forEach( i -> l_groupAtomic.set( ( (ILiteral) i ).values().findFirst().get().raw() ) );
198  return l_groupAtomic.get();
199  }
200 
201 
205  @IAgentActionFilter
206  @IAgentActionName( name = "start/election" )
207 
208  public void startElection()
209  {
210  final CGroup l_group = this.determineGroup();
211  l_group.triggerAgents( this );
212  }
213 
219  @IAgentActionFilter
220  @IAgentActionName( name = "store/vote" )
221  public void storeVote( final String p_agentName, final BitVector p_vote )
222  {
223  final CGroup l_group = this.determineGroup();
224 
225  m_agents.add( l_group.determineAgent( p_agentName ) );
226  m_bitVotes.add( p_vote );
227 
228  if ( m_bitVotes.size() == l_group.size() )
229  {
230 
231  final ITrigger l_trigger = CTrigger.from(
232  ITrigger.EType.ADDGOAL,
233  CLiteral.from(
234  "all/votes/received" )
235 
236  );
237 
238  System.out.println( " CChairAgent.java: all votes received " );
239 
240  this.trigger( l_trigger );
241  }
242  }
243 
244  private BitVector toBV( final AtomicIntegerArray p_vote )
245  {
246  final BitVector l_bitVector = new BitVector( p_vote.length() );
247  for ( int i = 0; i < p_vote.length(); i++ )
248  if ( p_vote.get( i ) == 1 )
249  l_bitVector.put( i, true );
250  return l_bitVector;
251  }
252 
257  @IAgentActionFilter
258  @IAgentActionName( name = "compute/result" )
259 
260  public void computeResult()
261  {
262  final CGroup l_group = this.determineGroup();
263 
264  final CMinisumApproval l_minisumApproval = new CMinisumApproval();
265 
266  final List<String> l_alternatives = new LinkedList<>();
267 
268  for ( char l_char : "ABCDEF".toCharArray() )
269 
270  l_alternatives.add( String.valueOf( l_char ) );
271 
272  System.out.println( " Alternatives: " + l_alternatives );
273 
274  System.out.println( " Votes: " + m_bitVotes );
275 
276  final BitVector l_comResultBV = l_minisumApproval.applyRuleBV( l_alternatives, m_bitVotes, 3 );
277 
278  System.out.println( " Result of election as BV: " + l_comResultBV );
279 
280  // set inProgress and readyForElection to false in group
281  l_group.reset();
282 
283  if ( "BASIC".equals( m_protocol ) )
284  {
285  this.beliefbase().add( l_group.updateBasic( this, l_comResultBV ) );
286  }
287 
288 
289  // if grouping is coordinated, reopen group for further voters
290  if ( "COORDINATED".equals( m_grouping ) && !l_group.finale() && !m_iterative )
291  {
292  System.out.println( " reopening group " );
293  m_environment.reopen( l_group );
294  }
295 
296  // for the iterative case, you need to differentiate between the final election and intermediate elections.
297  if ( "ITERATIVE".equals( m_protocol ) && ( l_group.finale() ) || m_iterative )
298  {
299  System.out.println( " Update iterative " );
300 
301  this.beliefbase().add( l_group.updateIterative( this, l_comResultBV, m_iteration ) );
302  return;
303  }
304 
305 
306  if ( "ITERATIVE".equals( m_protocol ) && !l_group.finale() )
307  {
308  System.out.println( " Update basic " );
309  this.beliefbase().add( l_group.updateBasic( this, l_comResultBV ) );
310  }
311 
312  // TODO test all cases
313 
314  }
315 
322  @IAgentActionFilter
323  @IAgentActionName( name = "store/diss" )
324 
325  public void storeDiss( final String p_name, final Double p_diss, final Integer p_iteration )
326  {
327  final CGroup l_group = this.determineGroup();
328 
329  m_dissList.add( p_diss );
330  final CVotingAgent l_dissAg = l_group.determineAgent( p_name );
331  m_dissVoters.add( l_dissAg );
332 
333  System.out.println( "Storing diss " + p_diss );
334 
335  if ( m_dissList.size() == l_group.size() )
336  {
337  final ITrigger l_trigger = CTrigger.from(
338  ITrigger.EType.ADDGOAL,
339  CLiteral.from(
340  "all/dissValues/received",
341  CRawTerm.from( p_iteration )
342  )
343 
344  );
345 
346  this.trigger( l_trigger );
347 
348  System.out.println( p_iteration + " All voters submitted their dissatisfaction value" );
349  }
350  }
351 
355  @IAgentActionFilter
356  @IAgentActionName( name = "remove/voter" )
357  public void removeVoter()
358  {
359  final CGroup l_group = this.determineGroup();
360 
361  final int l_maxIndex = this.getMaxIndex( m_dissList );
362  final double l_max = m_dissList.get( l_maxIndex );
363  System.out.println( " max diss is " + l_max );
364 
365  if ( l_max > m_dissThreshold )
366  {
367  System.out.println( " Determining most dissatisfied voter " );
368  final CVotingAgent l_maxDissAg = m_dissVoters.get( l_maxIndex );
369  System.out.println( " Most dissatisfied voter is " + l_maxDissAg.name() );
370  // remove vote of most dissatisfied voter from list
371  m_bitVotes.remove( l_maxDissAg.getBitVote() );
372  m_dissVoters.remove( l_maxDissAg );
373  l_group.remove( l_maxDissAg );
374 
375  System.out.println( "Removing " + l_maxDissAg.name() );
376 
377  // remove diss Values for next iteration
378  m_dissList.clear();
379 
380  m_iterative = true;
381  l_group.makeReady();
382 
383  if ( l_group.size() == 0 )
384  System.out.println( " Voter list is empty, we are done " );
385 
386  return;
387  }
388 
389  System.out.println( " No dissatisfied voter left, we are done " );
390  }
391 
392  private int getMaxIndex( final List<Double> p_dissValues )
393  {
394  int l_maxIndex = 0;
395  for ( int i = 0; i < p_dissValues.size(); i++ )
396  {
397  if ( p_dissValues.get( i ) > p_dissValues.get( l_maxIndex ) )
398  {
399  System.out.println( " changed max index to " + i + " diss: " + p_dissValues.get( i ) );
400  l_maxIndex = i;
401  }
402  }
403  return l_maxIndex;
404  }
405 
410  public static final class CChairAgentGenerator extends IBaseAgentGenerator<CChairAgent>
411  {
412 
417 
421  private final AtomicLong m_agentcounter = new AtomicLong();
422 
423  private final String m_grouping;
424  private String m_protocol;
425  private final String m_fileName;
426 
435  public CChairAgentGenerator( final InputStream p_stream, final CEnvironment p_environment, final String p_grouping, final String p_protocol,
436  final String p_fileName
437  ) throws Exception
438  {
439  super(
440  // input ASL stream
441  p_stream,
442 
443  // a set with all possible actions for the agent
444  Stream.concat(
445  // we use all build-in actions of LightJason
446  CCommon.actionsFromPackage(),
447  Stream.concat(
448  // use the actions which are defined inside the agent class
449  CCommon.actionsFromAgentClass( CChairAgent.class ),
450  // add VotingAgent related external actions
451  Stream.of(
452 
453  )
454  )
455  // build the set with a collector
456  ).collect( Collectors.toSet() ),
457 
458  // aggregation function for the optimisation function, here
459  // we use an empty function
460  IAggregation.EMPTY
461  );
462  m_environment = p_environment;
463  m_grouping = p_grouping;
464  m_protocol = p_protocol;
465  m_fileName = p_fileName;
466  }
467 
474  @Override
475  public final CChairAgent generatesingle( final Object... p_data )
476  {
477  final CChairAgent l_chairAgent = new CChairAgent(
478  // create a string with the agent name "chair <number>"
479  // get the value of the counter first and increment, build the agent
480  // name with message format (see Java documentation)
481  MessageFormat.format( "chair {0}", m_agentcounter.getAndIncrement() ), m_configuration, m_environment, m_grouping, m_protocol, m_fileName );
482  l_chairAgent.sleep( Integer.MAX_VALUE );
483  return l_chairAgent;
484  }
485 
486  }
487 }
int getMaxIndex(final List< Double > p_dissValues)
ILiteral detectGroup(final CChairAgent p_chairAgent)
detect group of chair agent
String m_grouping
grouping algorithm: "RANDOM" or "COORDINATED"
void storeVote(final String p_agentName, final BitVector p_vote)
store vote
CChairAgentGenerator(final InputStream p_stream, final CEnvironment p_environment, final String p_grouping, final String p_protocol, final String p_fileName)
constructor of the generator
Created by sophie on 21.02.17.
final CChairAgent generatesingle(final Object...p_data)
generator method of the agent
void removeVoter()
remove most dissatisfied voter
final CEnvironment m_environment
environment
ILiteral updateIterative(final CChairAgent p_chairAgent, final BitVector p_result, final int p_iteration)
update group literal for chair agent ( for random grouping )
Definition: CGroup.java:219
CChairAgent(final String p_name, final IAgentConfiguration< CChairAgent > p_configuration, final CEnvironment p_environment, final String p_grouping, final String p_protocol, final String p_fileName)
constructor of the agent
final AtomicLong m_agentcounter
Current free agent id, needs to be thread-safe, therefore using AtomicLong.
void storeDiss(final String p_name, final Double p_diss, final Integer p_iteration)
store dissatisfaction value
Created by sophie on 24.04.17.
Definition: CGroup.java:42
void computeResult()
compute result of election
BitVector toBV(final AtomicIntegerArray p_vote)
BDI agent with voting capabilities.
ILiteral updateBasic(final CChairAgent p_chairAgent, final BitVector p_result)
update group literal for chair agent ( for random grouping )
Definition: CGroup.java:194