mirror of
				https://github.com/gsi-upm/soil
				synced 2025-11-04 09:28:16 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			05f7f49233
			...
			e860bdb922
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e860bdb922 | ||
| 
						 | 
					d6b684c1c1 | 
@@ -3,6 +3,13 @@ All notable changes to this project will be documented in this file.
 | 
			
		||||
 | 
			
		||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 | 
			
		||||
 | 
			
		||||
## [0.15.2]
 | 
			
		||||
### Fixed
 | 
			
		||||
* Pass the right known_modules and parameters to stats discovery in simulation
 | 
			
		||||
* The configuration file must exist when launching through the CLI. If it doesn't, an error will be logged
 | 
			
		||||
* Minor changes in the documentation of the CLI arguments
 | 
			
		||||
### Changed
 | 
			
		||||
* Stats are now exported by default
 | 
			
		||||
## [0.15.1]
 | 
			
		||||
### Added
 | 
			
		||||
* read-only `History`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								docs/requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ipython==7.23
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
0.15.1
 | 
			
		||||
0.15.2
 | 
			
		||||
@@ -23,13 +23,15 @@ def main():
 | 
			
		||||
    import argparse
 | 
			
		||||
    from . import simulation
 | 
			
		||||
 | 
			
		||||
    logging.info('Running SOIL version: {}'.format(__version__))
 | 
			
		||||
    logger.info('Running SOIL version: {}'.format(__version__))
 | 
			
		||||
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Run a SOIL simulation')
 | 
			
		||||
    parser.add_argument('file', type=str,
 | 
			
		||||
                        nargs="?",
 | 
			
		||||
                        default='simulation.yml',
 | 
			
		||||
                        help='python module containing the simulation configuration.')
 | 
			
		||||
                        help='Configuration file for the simulation (e.g., YAML or JSON)')
 | 
			
		||||
    parser.add_argument('--version', action='store_true',
 | 
			
		||||
                        help='Show version info and exit')
 | 
			
		||||
    parser.add_argument('--module', '-m', type=str,
 | 
			
		||||
                        help='file containing the code of any custom agents.')
 | 
			
		||||
    parser.add_argument('--dry-run', '--dry', action='store_true',
 | 
			
		||||
@@ -52,12 +54,15 @@ def main():
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    logging.basicConfig(level=getattr(logging, (args.level or 'INFO').upper()))
 | 
			
		||||
 | 
			
		||||
    if args.version:
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    if os.getcwd() not in sys.path:
 | 
			
		||||
        sys.path.append(os.getcwd())
 | 
			
		||||
    if args.module:
 | 
			
		||||
        importlib.import_module(args.module)
 | 
			
		||||
 | 
			
		||||
    logging.info('Loading config file: {}'.format(args.file))
 | 
			
		||||
    logger.info('Loading config file: {}'.format(args.file))
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        exporters = list(args.exporter or ['default', ])
 | 
			
		||||
@@ -68,6 +73,10 @@ def main():
 | 
			
		||||
        exp_params = {}
 | 
			
		||||
        if args.dry_run:
 | 
			
		||||
            exp_params['copy_to'] = sys.stdout
 | 
			
		||||
 | 
			
		||||
        if not os.path.exists(args.file):
 | 
			
		||||
            logger.error('Please, input a valid file')
 | 
			
		||||
            return
 | 
			
		||||
        simulation.run_from_config(args.file,
 | 
			
		||||
                                   dry_run=args.dry_run,
 | 
			
		||||
                                   exporters=exporters,
 | 
			
		||||
 
 | 
			
		||||
@@ -14,15 +14,6 @@ from .utils import open_or_reuse, logger, timer
 | 
			
		||||
from . import utils
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def for_sim(simulation, names, *args, **kwargs):
 | 
			
		||||
    '''Return the set of exporters for a simulation, given the exporter names'''
 | 
			
		||||
    exporters = []
 | 
			
		||||
    for name in names:
 | 
			
		||||
        mod = deserialize(name, known_modules=['soil.exporters'])
 | 
			
		||||
        exporters.append(mod(simulation, *args, **kwargs))
 | 
			
		||||
    return exporters
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DryRunner(BytesIO):
 | 
			
		||||
    def __init__(self, fname, *args, copy_to=None, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
@@ -38,8 +29,12 @@ class DryRunner(BytesIO):
 | 
			
		||||
            super().write(bytes(txt, 'utf-8'))
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
        logger.info('**Not** written to {} (dry run mode):\n\n{}\n\n'.format(self.__fname,
 | 
			
		||||
                                                                       self.getvalue().decode()))
 | 
			
		||||
        content = '(binary data not shown)'
 | 
			
		||||
        try:
 | 
			
		||||
            content = self.getvalue().decode()
 | 
			
		||||
        except UnicodeDecodeError:
 | 
			
		||||
            pass
 | 
			
		||||
        logger.info('**Not** written to {} (dry run mode):\n\n{}\n\n'.format(self.__fname, content))
 | 
			
		||||
        super().close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -99,6 +94,12 @@ class default(Exporter):
 | 
			
		||||
                with self.output('{}.sqlite'.format(env.name), mode='wb') as f:
 | 
			
		||||
                    env.dump_sqlite(f)
 | 
			
		||||
 | 
			
		||||
    def end(self, stats):
 | 
			
		||||
          with timer('Dumping simulation {}\'s stats'.format(self.simulation.name)):
 | 
			
		||||
              with self.output('{}.sqlite'.format(self.simulation.name), mode='wb') as f:
 | 
			
		||||
                  self.simulation.dump_sqlite(f)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class csv(Exporter):
 | 
			
		||||
    '''Export the state of each environment (and its agents) in a separate CSV file'''
 | 
			
		||||
 
 | 
			
		||||
@@ -208,3 +208,13 @@ def deserialize(type_, value=None, **kwargs):
 | 
			
		||||
    if value is None:
 | 
			
		||||
        return des
 | 
			
		||||
    return des(value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def deserialize_all(names, *args, known_modules=['soil'], **kwargs):
 | 
			
		||||
    '''Return the set of exporters for a simulation, given the exporter names'''
 | 
			
		||||
    exporters = []
 | 
			
		||||
    for name in names:
 | 
			
		||||
        mod = deserialize(name, known_modules=known_modules)
 | 
			
		||||
        exporters.append(mod(*args, **kwargs))
 | 
			
		||||
    return exporters
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import pickle
 | 
			
		||||
from . import serialization, utils, basestring, agents
 | 
			
		||||
from .environment import Environment
 | 
			
		||||
from .utils import logger
 | 
			
		||||
from .exporters import default, for_sim as exporters_for_sim
 | 
			
		||||
from .exporters import default
 | 
			
		||||
from .stats import defaultStats
 | 
			
		||||
from .history import History
 | 
			
		||||
 | 
			
		||||
@@ -133,7 +133,7 @@ class Simulation:
 | 
			
		||||
                                              self.topology)
 | 
			
		||||
 | 
			
		||||
        self._history = History(name=self.name,
 | 
			
		||||
                               backup=False)
 | 
			
		||||
                                backup=False)
 | 
			
		||||
 | 
			
		||||
    def run_simulation(self, *args, **kwargs):
 | 
			
		||||
        return self.run(*args, **kwargs)
 | 
			
		||||
@@ -167,14 +167,16 @@ class Simulation:
 | 
			
		||||
            logger.setLevel(log_level)
 | 
			
		||||
        logger.info('Using exporters: %s', exporters or [])
 | 
			
		||||
        logger.info('Output directory: %s', outdir)
 | 
			
		||||
        exporters = exporters_for_sim(self,
 | 
			
		||||
                                      exporters,
 | 
			
		||||
                                      dry_run=dry_run,
 | 
			
		||||
                                      outdir=outdir,
 | 
			
		||||
                                      **exporter_params)
 | 
			
		||||
        stats = exporters_for_sim(self,
 | 
			
		||||
                                  stats,
 | 
			
		||||
                                  **stats_params)
 | 
			
		||||
        exporters = serialization.deserialize_all(exporters,
 | 
			
		||||
                                                  simulation=self,
 | 
			
		||||
                                                  known_modules=['soil.exporters',],
 | 
			
		||||
                                                  dry_run=dry_run,
 | 
			
		||||
                                                  outdir=outdir,
 | 
			
		||||
                                                  **exporter_params)
 | 
			
		||||
        stats = serialization.deserialize_all(simulation=self,
 | 
			
		||||
                                              names=stats,
 | 
			
		||||
                                              known_modules=['soil.stats',],
 | 
			
		||||
                                              **stats_params)
 | 
			
		||||
 | 
			
		||||
        with utils.timer('simulation {}'.format(self.name)):
 | 
			
		||||
            for stat in stats:
 | 
			
		||||
@@ -293,6 +295,9 @@ class Simulation:
 | 
			
		||||
        with utils.open_or_reuse(f, 'wb') as f:
 | 
			
		||||
            pickle.dump(self, f)
 | 
			
		||||
 | 
			
		||||
    def dump_sqlite(self, f):
 | 
			
		||||
        return self._history.dump(f)
 | 
			
		||||
 | 
			
		||||
    def __getstate__(self):
 | 
			
		||||
        state={}
 | 
			
		||||
        for k, v in self.__dict__.items():
 | 
			
		||||
 
 | 
			
		||||
@@ -74,10 +74,10 @@ class Exporters(TestCase):
 | 
			
		||||
        s = simulation.from_config(config)
 | 
			
		||||
        tmpdir = tempfile.mkdtemp()
 | 
			
		||||
        envs = s.run_simulation(exporters=[
 | 
			
		||||
            exporters.default,
 | 
			
		||||
            exporters.csv,
 | 
			
		||||
            exporters.gexf,
 | 
			
		||||
        ],
 | 
			
		||||
                                    exporters.default,
 | 
			
		||||
                                    exporters.csv,
 | 
			
		||||
                                    exporters.gexf,
 | 
			
		||||
                                ],
 | 
			
		||||
                                stats=[distribution,],
 | 
			
		||||
                                outdir=tmpdir,
 | 
			
		||||
                                exporter_params={'copy_to': output})
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user