- 11 Feb, 2014 2 commits
-
-
Jason Rhinelander authored
-
Jason Rhinelander authored
-
- 03 Feb, 2014 11 commits
-
-
Jason Rhinelander authored
Cancelling a reservation (which new MUPD code does sometimes) was not quite working because the tolerance was too low and thus negativity errors would result. This was supposed to be handled in the Firm already--and indeed it was within transfer(), which used transferApprox with its own epsilon, but release() wasn't passing epsilon and was getting Bundle's default (1e-13) instead of the desired 1e-10.
-
Jason Rhinelander authored
Typically a jump happens because the last step was too big and overshot whatever we were aiming for, so reduce step size when jumping to hopefully get back on track.
-
Jason Rhinelander authored
Every period was pretty messy--every 3 seems to do better
-
Jason Rhinelander authored
-
Jason Rhinelander authored
- Made locking more granular: we only lock markets when needed now, instead of getting a huge lock of all markets. - Markets becoming infeasible is a bigger problem now: other agents may be participating in markets while they aren't locked because of the above. Thus added an exception for handling this; when the exception gets thrown, MUPD redoes its optimization. Since it isn't being hit all that much, this, combined with the weaker locking behaviour, improves MUPD performance noticeably.
-
Jason Rhinelander authored
Fixed copy-and-paste typo from when Market locking code was copied into Firm.
-
Jason Rhinelander authored
Lock with a vector instead of a single member used to be pointless, and is now actually worse for performance (since Lock no longer uses a vector).
-
Jason Rhinelander authored
The method for removing a single member was in the .hpp but not actually implemented in the .cpp.
-
Jason Rhinelander authored
Converted Firm::Reservation and Market::Reservation state tracking to a single enum class (added to eris/types.hpp) instead of the dual bool (avoiding the "don't look at `completed` if `active` is true" design problem. This change also includes a bug fix for destruction: the market reservation destructor was checking !completed which is wrong in so many ways: it should have been checking just 'active' (not even '!active') instead. Using a single enum state revealed the bug.
-
Jason Rhinelander authored
-
Jason Rhinelander authored
-
- 31 Jan, 2014 6 commits
-
-
Jason Rhinelander authored
-
Jason Rhinelander authored
The default max_step means whatever is being stepped increases by (at most) 50% and decreases by (at most) 33% in a single step. Without this, initial conditions far off the equilibrium have a tendency to massively overshoot the equilibrium.
-
Jason Rhinelander authored
Added the ability to remove a subset of members from a Lock. This returns a new Lock consisting of the removed members--if the returned lock isn't used, it is released immediately, thus freeing the lock on the given members. This also involved converting Lock's internal vector implementation to a multiset, which required substantially reworking the locking code into using iterators on the multiset instead of indices.
-
Jason Rhinelander authored
Added the ability to add a new member to a lock (which might require releasing the existing lock, if the new member can't be locked right away). Also added the ability to transfer one lock's members to another. This requires no new locking attempts, but does require that the two locks have the same status (i.e. same read/write, and same locked/released status).
-
Jason Rhinelander authored
MUPD was causing a feasibility error because market feasibility was being checked before getting a market lock, which meant the market could be feasible, but after the lock might not be feasible anymore, in which case allocations failed with threads. Moving the feasibility check to after the big market write lock fixes that.
-
Jason Rhinelander authored
-
- 07 Jan, 2014 1 commit
-
-
Jason Rhinelander authored
-
- 08 Dec, 2013 1 commit
-
-
Jason Rhinelander authored
An agent class that has both a position and assets needs to be able to inherit from both AssetAgent and PositionalAgent, which requires that those both inherit from Agent virtually.
-
- 07 Dec, 2013 1 commit
-
-
Jason Rhinelander authored
New PositionalAgent subclass supports distance calculations, automatic wrapping when moving past a boundary, wrapping along just certain dimensions. - Explicitly added an initializer_list: the generic Container interface won't automatically match an initializer_list because the compiler can't deduce the type of initializer list accepted, and until it deduces that, it can't match the generic container. - Removed rvalue PositionalAgent constructor: it's wrong, since boundary1 and boundary2 are *not* the lower and upper boundaries: rather the min and max coordinates of each become lower and upper coordinates. - Removed the 1-, 2-, 3-, and 6-double-argument PositionalAgent constructors; by accepting Positions we already implicitly support initializer lists, so PositionalAgent({a,b}, {c,d}, {e,f}) works as expected: plus it's clearer than PositionalAgent(a,b,c,d,e,f). - Likewise for the 2- and 3-argument moveTo and moveBy methods. - Made the various boundary methods of PositionalAgent virtual because CircularPosAgent needs to override them (since wrapping boundaries aren't really boundaries). - Default lower_bound_ and upper_bound_ to zero vectors of the proper length (they get reset if boundaries apply, and are ignored if there are no boundaries). - Added pos-agent-test for testing various agent movement and wrapping methods.
-
- 06 Dec, 2013 2 commits
-
-
Jason Rhinelander authored
Position's constructor can now take any sort of container, not just an initializer_list. Added Position(vector<double>&&) which takes over the vector rather than copying it. Moved Position(const size_t&) to static Position::zero(const size_t&) to avoid things like Position({3.0}) becoming ambiguous (either an initializer list or a downcast to size_t). Changed various loop ints to size_ts to avoid gcc warning Updated PositionalAgent for Position changes
-
Jason Rhinelander authored
-
- 03 Dec, 2013 4 commits
-
-
Jason Rhinelander authored
This was probably leftover from a bit that was generated using preprocessor macros.
-
Jason Rhinelander authored
Maintaining the no-visible-changes should be a practice, not code enforced; needing to add mutable to all sorts of variables is a pain, ugly, and really doesn't accomplish much. Better just to let it be non-const, and not to change things by convention rather than misusing language features.
-
Jason Rhinelander authored
Since all this code is already bounds-safe, it should be a bit faster.
-
Jason Rhinelander authored
subdimensions({1, 3}) extracts the 2nd and 4th dimensions from a Position object. Converted ints to size_ts where appropriate. Made [] faster by simplying mapping to the [] of the underlying vector without doing bounds checking. at() calls vector.at(), which does bounds checking.
-
- 25 Nov, 2013 2 commits
-
-
Jason Rhinelander authored
Somehow I undid the PositionalAgent virtual method changes in the previous big commit. This adds them back in.
-
Jason Rhinelander authored
If eris had any releases yet, this would be a major version increment release. Optimization redesign ===================== - Overhauled the way optimization works. Now *any* member class can be an optimizer, and only implements the specific optimization methods that it wants, by inheriting from the appropriate interfaces in the new eris/Optimize.hpp header. - This means an Agent can have interopt code, intraopt code, or no optimization code in its class at all. - optimization methods are now prefixed with "inter" or "intra" since they are no longer contained with special optimization classes. This also avoids a potential conflict between classes that want both intra and inter optimize() and/or apply() methods. - Goods and Markets can now have optimization code, too, by simplying inheriting from the appropriate interopt::* or intraopt::* interface class(es). - Got rid of InterOptimizer and IntraOptimizer base classes. - Eris now has optimizer lists for each type of optimization stage, determined when a Member (of any type) is added or removed; this speeds things up quite a bit, because we don't have to bother checking every InterOpt/IntraOpt/Agent member to call its RunStage method(s), especially since most of them are empty. - This also fixes the weird design of having Agent->advance(), but all the other interopt methods under InterOptimizer. - All interOpt and intraOpt-related methods are now gone. A new set of "other" methods was added, so that non-agent/good/market objects, such as objects that only do optimization, can be added to the simulation. - Member is no longer abstract; while it was before a base class for the 5 core types (Agent, Good, Market, InterOptimizer, IntraOptimizer), it's now a base for the first three, plus anything else; in particular, classes that are pure optimizers will now typically inherit from Member plus the optimization interfaces they need. - new insertOptimizers()/removeOptimizers() methods are called when adding or removing any sort of member; it figures out whether the member is castable to the various interopt::* and intraopt::* classes, and if so, records the member as an optimizer of the appropriate class. Threads changes =============== - Got rid of supporting different threading models; everything now works as the old Sequential model. Preallocating had a very minimal performance benefit, at best, since the locking was replaced with an atomic queue index which works much faster. The minimal performance increase (on the order of a couple percent in the voting simulation) isn't worth the code complication (needing to worry about per-thread queues, in particular). Interface changes ================= - createAgent<A>(), createGood<G>(), etc. classes are gone now, replaced with a single create<T>() method. This is a drop-in replacement for all of the above as it determines what the member category is by looking at T. - Likewise for clone*() - Likewise for remove*() - agentFilter, goodFilter, etc. are renamed to the much better choice agents(), goods(), etc., and now return a vector instead of the unordered_map. This is nice: agents() is now a vector of all agents (agentFilter() already was that, but it wasn't obvious from the name), agents<Foo> is only Foo (and Foo-derived) agents, etc. - Member.writeLock() and .readLock() now take a variable number of SharedMember<T> arguments. For example: foo->writeLock(other1, other2). Previously you'd have to build a vector or list (or some other iterable object), add other1 and other2 to it, then call read/writeLock(). - The versions of Member.writeLock() and .readLock() that took an iterable object of pairs (e.g. unordered_map) are now gone, since agents/goods/etc. now return vectors instead of the unordered_maps agentFilter/goodFilter/etc. used to return. Member changes ============== - WalrasianPricer is gone: its code is now in QMarket, which declares itself as the appropriate intraopt::* providers. WalrasianPricer was so tightly tied to QMarket that it wasn't useful as an independent class anyway. - Agent is now a simpler class, *without* an assets Bundle. The assets() Bundle is now provided by the eris::agent::AssetsAgent subclass instead. This makes sense since the assets bundle was pointless for PositionalAgents, for example, which don't care about the assets clearing (and don't need the interopt::Advance optimizer just to clear assets). Other small changes =================== - SharedMember now has a < operator, so that SharedMembers can be added to ordered containers like std::set. - Discovered (and used) std::type_index for filter_cache_ keys instead of calling .hash_code() on the type_info object. - Simplified various bits of highly repetitive code with macros - Got rid of the unique_ptr<> hack from Simulation around agents_, goods_, etc. It was needed because SharedMember<Agent> wasn't directly constructible, but that hasn't been true for a while. - Slightly optimized the thread signalling code to only signal the master from the last thread to finish the stage. - Moved RunStage from Simulation::RunStage to just RunStage in types.h
-
- 20 Nov, 2013 5 commits
-
-
Jason Rhinelander authored
-
Jason Rhinelander authored
One sync lock wasn't ideal: split it into two: one on stage waiting, one on done waiting.
-
Jason Rhinelander authored
t() is 1 for the first iteration, 2 for the second, etc. Interopts that run between periods x and x+1 get x+1 for t().
-
Jason Rhinelander authored
This seems to make a marginal difference in speed, but reduces code size a bit.
-
Jason Rhinelander authored
The base versions of distance(), moveTo(), and truncate() are now virtual, since classes might want to override them (for example, to support a circular positioning in one dimension, where moving to 1.1 actually wraps around and moves to 0.1.
-
- 19 Nov, 2013 2 commits
-
-
Jason Rhinelander authored
Reimplemented threading queuing with three new methods, controllable via simulation->threadModel(...) ThreadModel::Preallocate preallocates jobs across threads; threads then just do their own thing ThreadModel::Sequential does what we did before (each thread accesses the queue in parallel). Changed this model to use an atomic_uint which is slightly faster than the previous big lock method, even though we are now back to copying eris_id_ts around ThreadModel::Hybrid calls new preallocate*() methods for each job (e.g. Agent::preallocateAdvance()): if they return true, the job gets put in one of the thread queues, otherwise it gets put in the shared queue. This should allow for a better mix when some jobs are slow and others are fast without the downside of prequeuing picking randomly suboptimal allocations.
-
Jason Rhinelander authored
-
- 07 Nov, 2013 3 commits
-
-
Jason Rhinelander authored
The threaded code now works and imposes only a miniscule performance penalty (especially when not activated, which is the default), so it's ready to come into the master branch.
-
Jason Rhinelander authored
This was added for code compatibility with the threaded branch, but the threaded branch no longer takes it (it got replaced with maxThreads(n)).
-
Jason Rhinelander authored
Completely overhauled locking code: Member::ParallelLock is gone; there is just Member::Lock which handles any number (including 1) of parallel locks. Also added lock manipulation (switching read <-> write, locking and releasing) to it. Thread running code is significant sped up by not using a queue, instead it just iterates through agents_/interopts_/intraopts_. Threading interface has changed: it's not set via simulation->maxThreads() instead of a run() argument. Threading can be avoided by setting maxThreads(0). maxThreads(1) still uses threading (albeit with a single thread), and seems to imposes only a couple percent penalty (now that we aren't copying everything into a queue).
-