Giter Club home page Giter Club logo

uia-sim's Introduction

UIA-SIM for Java, DESim4J

Build Status codecov Codacy Badge License

DESim4J is a Java port of SimPy, process-based discrete event simulation framework.

DESim4J aims to port the concepts used in SimPy to the Java world. Because there is no yield keyword in Java, the framework also implements a yield-like API in package uia.cor to meet some coroutine scenarios.

The ROAD is a sub-project that build a abstract simulator of the manufacturing factory.

API

package uia.cor

The package provides yield-like API. The main concept is

Generator gen = Yield.accept(yield -> ::function);
  • Yield

    • yield.call(Object) - pass a value to paired Generator.
    • yield.close() - stop iteration.
  • Generator

    • gen.next() - notify ::function to prepare next value.
    • gen.errorNext() - notify ::function to prepare next value.
    • gen.getValue() - Get the value from yield.setValue(Object)
    • gen.error(ex) - send back an exception.
    • gen.send(Object) - send back a value to yield.
    • gen.close() - stop yield iterable.

Below is a simple workflow of Yield-Generator:

public class YieldTest {

    @Test
    public void testCallFor() {
        // 1
        Generator<Integer> gen = Yield.accept(this::callFor); 
            // 2, 5
            while(gen.next()) {
                // 4
                System.out.println("value=" + gen.getValue());
        }
    }

    /**
     * iterable work
     */
    public void callFor(Yield<Integer> yield) {
        for(int i = 0; i < 10; i++) {
            // 3
            yield.call(i);
        }
    }
}
  1. Generator<Integer> gen = Yield.accept(this::callFor) - Create a Yield object and pass to callFor method. Return paired Generator.
  2. gen.next() - Ask if there is a new value or not.
  3. yield.call(i) - Pass a new value to the generator and block until invoking gen.next() again.
  4. gen.getValue() - Get the new value passed by yield.call(i).
  5. while(gen.next()) - Repeat until completing the for loop.

Use Yield2Way if iteration needs to get a result from yield.call(value).

public class Yield2WayTest {

    @Test
    public void testSum2() {
        Generator2Way<Integer, Integer> gen = Yield2Way.accept(this::sum2);
        int i = 0;
        // 4
        while(gen.next()) {
            // 2
            i = gen.getValue();
            System.out.println("value=" + i);
            // 3
            gen.send(i * i);
        }
    }

    /**
     * iterable work
     */
    public void sum2(Yield2Way<Integer, Integer> yield) {
        int i = 1;
        int sum = 0;
        while(i <= 10) {
            // 1, 5
            int v = yield.call(i++);    // waiting a result
            sum += v;
        }
        System.out.println("  sum=" + sum);
    }
}
  1. yield.call(i++) - Pass a new value to the generator and block until invoking gen.next() again.
  2. gen.getValue() - Get the new value passed by yield.call(i).
  3. gen.send(i * i) - Send back a result but step 1 is still blocking.
  4. gen.next() - Ask if there is a new value or not and release step 1 at the same time.
  5. int v = yield.call(i++) - Get the result passed by gen.send(i * i).

Class Diagram

classDiagram
    Generator --> Yield
    Consumer ..> Yield
    Yield <-- Yieldable

    <<Iterable>> Consumer

    Generator: next() boolean
    Generator: next(R) boolean
    Generator: getValue() T
    Yield: call(T)
    Yield: send(R)
    Yield: next(boolean stop) boolean
    Yield: getValue() T
    Consumer: accept(Yield)
    Yieldable: run()

Sequence Diagram

sequenceDiagram
    autonumber
    Controller --) Consumer: new()
    Controller ->> +Yield: accept()
    Yield -->> +Generator: new()
    Yield --) -Controller: generator

    Yield --) Consumer: accept()
    note over Yield: in a new Thread
    loop thread-iterable
        Consumer ->> +Yield: call(T)
        note right of Consumer: send a value to the Controller
        Yield ->> Yield: notifyAll()
        note over Yield: notify Step-14 to get next value
        Yield --) Yield: wait()
        Yield --) -Consumer: 
        note over Yield: wait Step-12 to notify
    end

    loop thread-main
        Controller ->> Generator: next()
        Generator ->> +Yield: next()
        Yield ->> Yield: notifyAll()
        note over Yield: notify Step-9 to build next value
        Yield --) Yield: wait()
        Yield --) -Generator: 
        note over Yield: wait Step-7 to notify
        Controller ->> Generator: T getValue()
        Generator ->> +Yield: T getValue()
        Yield --) -Generator: value
        note right of Controller: get last value from the Generator
    end    

package uia.sim

The package is core framework of process-based discrete event simulation.

Some documents

Core Concept

  1. Create a event stream
flowchart LR;
    id1[[*E00]]-->E20;
    E20-->E50;
    E50-->E90;
  1. Execute head event E00, and create a new event E55. The event stream becomes
flowchart LR;
    id1[[*E20]]-->E50;
    E50-->id2([E55]);
    id2([E55])-->E90;
  1. Execute head event E20, and create a new event E53. The event stream becomes
flowchart LR;
    id1[[*E50]]-->id2([E53]);
    id2([E53])-->id3([E55]);
    id3([E55])-->E90;
  1. Execute all events with ordering.
flowchart LR;
    id1[[*E53]]-->id2([E55]);
    id2([E55])-->E90;
flowchart LR;
    id1[[*E55]]-->E90;
flowchart LR;
    id1[[*E90]];

Class Diagram

classDiagram

    Env --* Job
    Initialize --|> Event
    Job --> Event
    Event <.. Yield
    Event -- * Callback 
    Callback -- Process
    Event <|-- Process
    Event <.. Processable
    Yield <-- Consumer
    Yield <-- Generator
    Consumer <|-- Processable
    Processable --> Process  
    Generator <-- Process

    <<coroutine>> Yield
    <<coroutine>> Generator
    <<coroutine>> Consumer
    <<case>> Processable

    Env: PriorityBlockingQueue~Job~ jobs

    Process: +resume(Event)

    Processable: +initial()
    Processable: +run()

    Event: List callables
    Event: +callback()

Sequence Diagram

  1. Work flow of events

    sequenceDiagram
        autonumber
        loop
            Env ->> +Env: poll()
            Env ->> Event: callback()
            Event ->> Process: resume(Event)
            Process --) Processable: // notify
            Processable ->> Env: // schedule a new event if needed
            Env --) Event: // new
            Env ->> -Env: // add a new event into the queue
            Processable --) Process: // notify
            Process ->> Event: addCallable()
        end
    
  2. Startup of a process

    sequenceDiagram
        autonumber
        Env ->> Event["Initialize"]: callback()
        Event["Initialize"] ->> +Process: resume(Event)
    
            Process ->> Event["Initialize"]: getValue()
            Process ->> +Generator: next(Object)
            Generator ->> Yield: send(Object)
            Generator ->> Yield: next(Boolean)
            Yield --) Processable: notifyAll()
            Processable ->> +Env: // schedule a new event if needed
            Env --) Event: new
            Env ->> -Env: // add a new event into the queue
            Processable ->> Yield: call(Event)
            Yield --) Generator: notifyAll()
            Generator --) -Process: 
            Process ->> Generator: getValue()
            Process ->> -Event: addCallable(Process::resume) // hook the Process and Event together
    

Test Case

Below is a Java test case compares with Python version.

Python

class School:
    def __init__(self, env):
        self.env = env
        self.class_ends = env.event()
        self.pupil_procs = [env.process(self.pupil()) for i in range(3)]
        self.bell_proc = env.process(self.bell())

    def bell(self):
        while True:
            yield self.env.timeout(45)
            self.class_ends.succeed()
            self.class_ends = self.env.event()
            print()

    def pupil(self):
        while True:
            yield self.class_ends
            print(r' \o/', end='')

env = Environment()
school = School(env)
env.run(200)

Java

public class SchoolTest {

    private Env env;

    private Event classEnd;

    public SchoolTest() {
        this.env = new Env();
        this.classEnd = this.env.event("classEnd");
        env.process("pupil-1", this::pupil);
        env.process("pupil-2", this::pupil);
        env.process("pupil-3", this::pupil);
        env.process("bell", this::bell);
    }

    public void bell(Yield<Event> yield) {
        while(yield.isAlive()) {
            yield.call(env.timeout(45));
            this.classEnd.succeed(null);
            this.classEnd = this.env.event("classEnd");
            System.out.println(String.format("\n%3d> bell is ringing...", this.env.getNow()));
        }
    }

    public void pupil(Yield<Event> yield) {
        while(yield.isAlive()) {
            yield.call(this.classEnd);
            System.out.print("\\o/ ");
        }
    }

    @Test
    public void test1() throws Exception {
        this.env.run(200);
    }
}

The framework is still building and testing. The next tasks are

  1. Add resources implementation.
  2. More stable of uia.cor package.
  3. More reasonable Exception control.
  4. More test cases to prove the framework.

Reference

SimPy Home

SimPy GitLab

Discrete-Event Simulation Wiki

uia-sim's People

Contributors

gazer2kanlin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.