Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/agentblocks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Standalone check for the AgentBlocks TIB reference implementation.
# This is the self-contained Java block from the RBB (agentblocks/TIB_BedDeM.java):
# no Repast, no Postgres, no build.xml -- just javac + java. It compiles the block
# and runs the example, and writes the output to the run summary.

name: AgentBlocks TIB example

on:
push:
branches: [ "master" ]
paths: [ "agentblocks/**", ".github/workflows/agentblocks.yml" ]
pull_request:
branches: [ "master" ]
paths: [ "agentblocks/**", ".github/workflows/agentblocks.yml" ]

jobs:
tib-example:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Compile and run the TIB block
run: |
set -e
mkdir -p out
javac -encoding UTF-8 -d out agentblocks/TIB_BedDeM.java
echo "## AgentBlocks TIB example output" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
java -cp out agentblocks.tib.TIBExample | tee -a "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
78 changes: 77 additions & 1 deletion .github/workflows/ant.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# This workflow will build a Java project with Ant
# This workflow builds the Java project with Ant, runs the tests, then runs the
# model headlessly and renders its real decision output onto the run summary.
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-ant

name: BedDeM CI
Expand All @@ -14,6 +15,13 @@ jobs:

runs-on: ubuntu-latest

# Needed so the test-results step can post a check + comment on the PR.
permissions:
checks: write
pull-requests: write
issues: write
contents: read

steps:
- uses: actions/checkout@v4
- name: Set up JDK 11
Expand All @@ -33,7 +41,75 @@ jobs:
ant junitreport
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always() # publish even when a test fails
with:
files: |
junit/**/*.xml
check_name: "Test Results"
comment_mode: always # always post/update a comment on the PR
comment_title: "BedDeM test results"
- name: Upload JUnit report
uses: actions/upload-artifact@v4
if: always() # keep the HTML/XML report even on failure
with:
name: junit-report
path: junit/

# ---- Run the model and show its real decision output ---------------------
# The batch (headless) run drives DummyReporter, which writes
# output/decisions.csv. output/ is gitignored, so this is produced fresh in
# the pipeline on every run -- nothing is committed.
- name: Run model (headless)
continue-on-error: true # keep going so we can locate output + diagnose
timeout-minutes: 10 # don't hang the job if the run stalls
run: |
# Runs the dummy (CSV) model headless via the run-headless target
# (beddem_simulator.HeadlessRun) -- no Swing GUI, so it works with no
# display. Produces output/decisions.csv.
rm -f output/decisions.csv
ant run-headless "-DECLIPSE_HOME=$(pwd)"
- name: Locate decision output
if: always()
# Repast's batch runner executes each run in its own instance directory, so
# DummyReporter's relative "output/decisions.csv" may land there rather than
# at the repo root. Find whatever the run produced and bring it back.
run: |
echo "Files produced by the run:"
find . -name 'decisions.csv' -o -name 'DummyOutput*.txt' 2>/dev/null || true
latest=$(find . -name 'decisions.csv' -printf '%T@ %p\n' 2>/dev/null | sort -nr | head -1 | cut -d' ' -f2-)
if [ -n "$latest" ] && [ "$latest" != "./output/decisions.csv" ]; then
mkdir -p output && cp "$latest" output/decisions.csv
echo "Copied $latest -> output/decisions.csv"
fi
echo "--- output/ ---"; ls -la output/ 2>&1 || echo "(no output dir)"
- name: Set up Python
if: always()
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Summarise decisions
if: always() # still report (or note "no output") if the run failed
run: |
python analysis/summarize_decisions.py > decision_summary.md
cat decision_summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Post decision results to PR
# Skipped automatically for PRs from forks (their token is read-only and
# cannot comment); the results still appear in the run summary + artifact.
if: always() && github.event_name == 'pull_request' && github.event.pull_request.head.repo.fork == false
continue-on-error: true # never fail the build just over the comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: tib-decisions # one comment, updated on each run
path: decision_summary.md
- name: Render decision chart
if: always()
run: |
pip install matplotlib
python analysis/plot_tib.py
- name: Upload decision chart
if: always()
uses: actions/upload-artifact@v4
with:
name: tib-decisions
path: analysis/tib_decisions.png
if-no-files-found: ignore
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ Repast.settings
/testbin/
junit/*
.idea/*

# Generated TIB charts
analysis/*.png
4 changes: 4 additions & 0 deletions MessageCenter.log4j.properties
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ log4j.logger.dummy.database.CSVReader = DEBUG, R
log4j.logger.framework.agent.core.TaskExecutionAgent = DEBUG, R
log4j.logger.framework.agent.reasoning.Determinant = DEBUG, R

# Per-determinant TIB scores (norm/role/self/emotion/facilitating/freq + time/cost).
# Comment this out to silence the determinant traces.
log4j.logger.dummy.agent.StandardDummyAgent = DEBUG, stdout, R

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=debug.log
log4j.appender.R.MaxFileSize=100KB
Expand Down
67 changes: 9 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,63 +58,16 @@ agentID,start_time,km,vehicle
```
This output corresponds to the `time_weight` set to 5 and `cost_weight` set to 1.

## Project structure
In this case we have example `<scenario>` called `dummy`. The directory structure:
* **`src`**
- `<scenario>.agent`: specific implementation of all agents for scenario and external inputs for processing
+ CommunicationComponent: decision communication
+ DecisionComponent: decision determinants definition
+ MemoryComponent: memory definition and feelings
+ PerceptionComponent: perception component of possibilities
+ StandardDummyAgent: definition of the agent and its functions
- `<scenario>.concept`: basic concepts used around model such as Task and Option available for agent
+ EnvironmentalState: state of the environment and availability
+ Feedback: feedback of the environment
+ InternalState: state of the environment
+ Option: environment options
+ Task: one task in the agent schedule with all its constraints
+ Vehicle: vehicle definition and properties
- `<scenario>.context`: context definitions usually taken from the GlobVariables file
+ AgentContext: context definition for agent
+ LocationContext: context definition for location
- `<scenario>.database`: data retrievers
+ CSVReader: reader for csv files
- `<scenario>.environment`: definitions of the environment
- `<scenario>.report`: contains scenario specific reporter classes.
+ Reporter classes: describes how what we want from the model. We can select which method to be run in Repast interface.
- `<scenario>.simulator`: contain the Repast controller, scheduler and logger of the project. This is the core function of Repast and you should not modify it. The two simulator classes here are ContextManager (the simulator controller and entry points of the simulator) and ThreadAgentScheduler (schedules the Tasks and execute them).
+ ContextManager: describes how the input should be read and can be modified to fit the project. Container of all the agents and locations.
- `framework.agent.core`: anything that is related to the agent's operation
+ IAgent: the Interface of agent. Contains some methods that an agent should have.
+ DefaultAgent: the standard agent that can be extended depend on the type of project. Its simulator operation is described in the step() method which is controlled by the Scheduler mentioned above.
+ StandardTraveller: the class used specific for transportation demand. Contains the logic to evaluate an option.
- `framework.agent.reasoning`: containing the TPB and TIB model and determinant interfaces
+ Determinant: standard determinant for evaluation of options
+ LeafDeterminant: base determinant node in decision making
+ ParentDeterminant: parent determinant in decision making model defines ranking options
+ TIBModel: Triandis decision making model, definition all base determinants according to this model
+ TPBModel: Theory of planned behavior model
- `framework.concept`: some basic concepts that are used around the model (i.e Task and Option available for the agent). Note that at the moment time is setup as hour and distance is in km. Also some classes that are implemented specifically for transportation demand.
+ EnvironmentalState: state of environment
+ Feedback: interface definition of feedback
+ InternalState: interface for agent state
+ Opinion: interface for agent opinion
+ Option: option interface
+ Task: task interface
- `framework.environment`: information of the environment where the agents reside in. (ex: available transportations, total demand, kms, spending for each mode, etc.).
+ Environment: interface for location of the agent its environment
- `framework.exception`: all the exceptions and how to handle them.

* **`data`**
- `csv_files`: two scenario example files one with `dummy` prefix and one without. Both are containing schedule for only for next day.
+ agents: list of all the agent and their parameters.
+ vehicle: list of all available transportation mode and their parameters.
+ schedule: list of all the events to be assigned to agents. At the moment, the price point of car is added at the end of the file name (ex: 0.0 mean car_price * 0.0). This is for when we want to run in batch mode where we want to define different price points in the demand curve.
+ location: list of all locations with available modes of transport
- testing: csv files for modular + system testing, will be generated if you run the testing classes.
- beddem_simulator.properties: locations of all the inputs, parameters and outputs of the model.
* **`your_project_name.rs`**: Define the inputs, outputs, parameters and observers for the model
## Scenario: Sion ↔ Sierre
The bundled scenario models a full TIB decision with **two locations** — Sion (`loc_id 1`) and Sierre (`loc_id 2`), both offering train + bus — and several agents with different attributes (weights and owned vehicles). Every TIB determinant is implemented in `StandardDummyAgent` (norm, role, self-concept, emotion, facilitating, habit, plus time/cost), each expressed as a **cost** (lower = better), so an agent picks the option with the lowest expected utility.

Everything is data-driven from `data/`:
- `agent.csv` — one row per agent: home location, funding, owned vehicles (`resources`), and the TIB weights.
- `location.csv` — `loc_id, train, bus, tram, name` (which transit each location offers).
- `schedule.0.csv` — the trips (`agent_id, start, km, time_limit, purpose`); a Sion↔Sierre trip is an 18 km row.
- `vehicle.csv` — the modes and their speed/cost.

Add agents, locations, or trips by editing those CSVs — the `ContextManager` loads them at startup. To see each determinant's score per mode, enable `dummy.agent.StandardDummyAgent = DEBUG` in `MessageCenter.log4j.properties`.

## Tested with versions
- Eclipse: 2024-03
Expand All @@ -129,5 +82,3 @@ To enable the debug logging for the BedDeM specific classes add or uncomment in
```bash
log4j.logger.dummy.database.CSVReader = DEBUG, stdout, R
```
Logger levels and the description of log4j architecture can be find [here](https://logging.apache.org/log4j/2.x/manual/architecture.html)

Loading
Loading