How can I print with Simpy which resource each customer goes to? - simulation

I have a two source simulation study. How can I print with Simpy which resource each customer goes to?
I am getting the sources as below, but how can I print which customer and which source, I am new in this field, could you help me please?
env = simpy.Environment()
server = simpy.Resource(env, 2)

The problem with simpy.Resource is its resources are generic, they have no unique id or other characteristics. simpy.Resource simple tracks the count of resources. If you want to track individual resources, you need to create your own resource class and use a simply.Store as your resource pool.
Here is a example
"""
Example of using resouces with a identity instead of
the resouces that come with simpy.Resource class
In this example, instead of using a simpy.Resource, I use
a simpy.Store. The resouce has a id, and task time
which allows one resouce to be faster then another.
programmer: Michel R. Gibbs
"""
import simpy
import random
class Entity():
"""
Simple entity with unique Id
"""
next_id = 1
def __init__(self):
self.id = Entity.next_id
Entity.next_id += 1
class MyResource():
"""
A resouce class where each resouce has a unique ID
and a different processing / task time
"""
next_id = 1
def __init__(self, task_time):
self.id = MyResource.next_id
MyResource.next_id += 1
self.task_time = task_time
def the_process(env, entity, resource_pool):
"""
A simple process where a entity grabs a resouce
takes some time to do the process based on the
processing speed of the seized resouce,
then relase the resouce
"""
print(f'{env.now} Entity {entity.id} in queue for resouce')
resource = yield resource_pool.get()
print(f'{env.now} Entity {entity.id} seized resouce {resource.id}')
yield env.timeout(resource.task_time)
resource_pool.put(resource)
print(f'{env.now} Entity {entity.id} finished task and released resouce {resource.id}')
def generate_arrivals(env, resouce_pool):
"""
generates a stream of entity arrivals
"""
while True:
yield env.timeout(random.uniform(1,7))
entity = Entity()
env.process(the_process(env, entity, resouce_pool))
# boot up sim
env = simpy.Environment()
resource_pool = simpy.Store(env)
resource_pool.put(MyResource(8))
resource_pool.put(MyResource(10))
env.process(generate_arrivals(env, resource_pool))
env.run(200)

Related

How can I listen for the creation of a specific model and create a new one (on a different table) based on this?

I have a User model with a referral_key attribute. I'd like to create a ReferralKeyRecord upon creation of a user. I've read tons of documentation and StackExchange to no avail.
This answer uses after_insert(), but I am not trying to alter or validate the class which is being inserted; I am trying to add a new object from a completely different model—and session.add() isn't supported.
This answer is closer to what I want, but the accepted answer (ultimately) uses after_flush(), which is far too general. I don't want to listen to events thrown whenever the DB is updated somehow. I want it to fire off when a specific model is created.
And something like the following...
#event.listens_for(User, 'after_flush')
def create_referral_record(mapper, connection, target):
session.add(ReferralRecord(key=instances.referral_key))
session.commit()
... results in No such event 'after_flush' for target '<class 'models.User'>. I've looked through SQLAlchemy's documentation (the core events and the ORM events) and see no events that indicate a specific model has been created. The closest thing in Mapper events is the after_insert method, and the closest thing in Session events is the after_flush() method. I imagine this is a pretty common thing to need to do, and would thus be surprised if there wasn't an easy event to listen to. I assume it'd be something like:
#event.listens_for(User, 'on_creation')
def create_referral_record(session, instance):
record = ReferralRecord(key=instance.referral_key)
session.add(record)
session.commit()
Does anyone know better than I?
Or why not create the Referral inside the User constructor?
from sqlalchemy.orm import Session, relationship, Mapper
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey, create_engine, event
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
def __init__(self):
self.referral = Referral()
id = Column(Integer(), primary_key=True)
referral = relationship('Referral', uselist=False)
class Referral(Base):
__tablename__ = 'referral'
id = Column(Integer(), primary_key=True)
user_id = Column(Integer(), ForeignKey('user.id'), nullable=False)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
session = Session(bind=engine)
session.add(User())
session.commit()
print(session.query(User).all())
print(session.query(Referral).all())
You can use the after_flush session event, and inside the event handler you can access the session's new objects (using session.new).
Example:
from sqlalchemy.orm import Session, relationship, Mapper
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey, create_engine, event
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = Column(Integer(), primary_key=True)
class Referral(Base):
__tablename__ = 'referral'
id = Column(Integer(), primary_key=True)
user_id = Column(Integer(), ForeignKey('user.id'), nullable=False)
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
session = Session(bind=engine)
#event.listens_for(session, 'after_flush')
def session_after_flush(session, flush_context):
for obj in session.new:
if isinstance(obj, User):
session.add(Referral(user_id=obj.id))
session.add(User())
session.commit()
print(session.query(User).all())
print(session.query(Referral).all())
Running this outputs:
[<__main__.User object at 0x00000203ABDF5400>]
[<__main__.Referral object at 0x00000203ABDF5710>]

EmbeddedDocumentSerializer runs query for every ReferenceField

I have following models and serializer the target is when serializer runs to have only one query:
Models:
class Assignee(EmbeddedDocument):
id = ObjectIdField(primary_key=True)
assignee_email = EmailField(required=True)
assignee_first_name = StringField(required=True)
assignee_last_name = StringField()
assignee_time = DateTimeField(required=True, default=datetime.datetime.utcnow)
user = ReferenceField('MongoUser', required=True)
user_id = ObjectIdField(required=True)
class MongoUser(Document):
email = EmailField(required=True, unique=True)
password = StringField(required=True)
first_name = StringField(required=True)
last_name = StringField()
assignees= EmbeddedDocumentListField(Assignee)
Serializers:
class MongoUserSerializer(DocumentSerializer):
assignees = AssigneeSerializer(many=True)
class Meta:
model = MongoUser
fields = ('id', 'email', 'first_name', 'last_name', 'assignees')
depth = 2
class AssigneeSerializer(EmbeddedDocumentSerializer):
class Meta:
model = Assignee
fields = ('assignee_first_name', 'assignee_last_name', 'user')
depth = 0
When checking the mongo profiler I have 2 queries for the MongoUser Document. If I remove the assignees field from the MongoUserSerializer then there is only one query.
As a workaround I've tried to use user_id field to store only ObjectId and changed AssigneeSerializer to:
class AssigneeSerializer(EmbeddedDocumentSerializer):
class Meta:
model = Assignee
fields = ('assignee_first_name', 'assignee_last_name', 'user_id')
depth = 0
But again there are 2 queries. I think that the serializer EmbeddedDocumentSerializer fetches all the fields and queries for ReferenceField and
fields = ('assignee_first_name', 'assignee_last_name', 'user_id')
works after the queries are made.
How to use ReferenceField and not run a separate query for each reference when serializing?
I ended up with a workaround and not using ReferenceField. Instead I am using ObjectIdField:
#user = ReferenceField("MongoUser", required=True) # Removed now
user = ObjectIdField(required=True)
And changed value assignment as follows:
- if assignee.user == MongoUser:
+ if assignee.user == MongoUser.id:
It is not the best way - we are not using ReferenceField functionality but it is better than creating 30 queries in the serializer.
Best Regards,
Kristian
It's a very interesting question and I think it is related to Mongoengine's DeReference policy: https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/dereference.py.
Namely, your mongoengine Documents have a method MongoUser.objects.select_related() with max_depth argument that should be large enough that Mongoengine traversed 3 levels of depth: MongoUser->assignees->Assignee->user and cached all the related MongoUser objects for current MongoUser instance. Probably, we should call this method somewhere in our DocumentSerializers in DRF-Mongoengine to prefetch the relations, but currently we don't.
See this post about classical DRF + Django ORM that explains, how to fight N+1 requests problem by doing prefetching in classical DRF. Basically, you need to override the get_queryset() method of your ModelViewSet to use select_related() method:
from rest_framework_mongoengine.viewsets import ModelViewSet
class MongoUserViewSet(ModelViewSet):
def get_queryset(self):
queryset = MongoUser.objects.all()
# Set up eager loading to avoid N+1 selects
queryset.select_related(max_depth=3)
return queryset
Unfortunately, I don't think that current implementation of ReferenceField in DRF-Mongoengine is smart enough to handle these querysets appropriately. May be ComboReferenceField will work?
Still, I've never used this feature yet and didn't have enough time to play with these settings myself, so I'd be grateful to you, if you shared your findings.

how to create multiple chatrooms using websockets in scala?

I'm trying to learn how to use WebSockets and Akka using the Chat example in the Play for Scala book.
In the book, there is one "ChatRoom" being created, and that's instantiated in the Chat controller with something as simple as this:
val room = Akka.system.actorOf(Props[ChatRoom])
I want to expand this example and have multiple chat rooms available instead of just one. A user can provide a string, which can be a chatroom "name", and that would create a new chatroom. Anyone that tries to join this chatroom would share a broadcast with each other, but not with people in another chatroom. Very similar to IRC.
My questions are the following:
1: How do I create a ChatRoom with a unique name if one does not already exist?
2: How can I check if the existing ChatRoom exists and get a reference to it?
The chatroom name will come via either the URL or a query parameter, that part will be trivial. I'm just not entirely sure how to uniquely identify the Akka ChatRoom and later retrieve that Actor by name.
You can name actors in Akka, so instead of having:
Akka.system.actorOf(Props[ChatRoom])
You would have:
Akka.system.actorOf(Props[ChatRoom],"room1")
Then, depending on the Akka version you're using, use either Akka.system.actorFor("room1") or Akka.system.actorSelection("room1") to get a reference to the wanted chat room.
Use the Akka EventBus trait. You can use eventBus and LookupClassification to implement topic based publish-subscribe where the "topic" is the roomID and the subscribers are either the actors for each room or the web-socket actors for each client.
import akka.event.EventBus
import akka.event.LookupClassification
final case class MsgEnvelope(topic: String, payload: Any)
/**
* Publishes the payload of the MsgEnvelope when the topic of the
* MsgEnvelope equals the String specified when subscribing.
*/
class LookupBusImpl extends EventBus with LookupClassification {
type Event = MsgEnvelope
type Classifier = String
type Subscriber = ActorRef
// is used for extracting the classifier from the incoming events
override protected def classify(event: Event): Classifier = event.topic
// will be invoked for each event for all subscribers which registered themselves
// for the event’s classifier
override protected def publish(event: Event, subscriber: Subscriber): Unit = {
subscriber ! event.payload
}
// must define a full order over the subscribers, expressed as expected from
// `java.lang.Comparable.compare`
override protected def compareSubscribers(a: Subscriber, b: Subscriber): Int =
a.compareTo(b)
// determines the initial size of the index data structure
// used internally (i.e. the expected number of different classifiers)
override protected def mapSize: Int = 128
}
Then register your actors (in reality you would keep a count of how many users are in each room and subscribe when users enter the room and unsubscribe and kill the actor when no-one is in the room)
val lookupBus = new LookupBusImpl
lookupBus.subscribe(room1Actor, "room1")
lookupBus.subscribe(room2Actor, "room2")
The message will be switched based on the roomID
lookupBus.publish(MsgEnvelope("room1", "hello room1"))
lookupBus.publish(MsgEnvelope("room2", "hello room2"))
lookupBus.publish(MsgEnvelope("room3", "hello dead letter"))

classic asp/vbscript class to track employees and performance metrics

I am trying to create a classic asp/vbscript class that will allow me to easily manage a small number of employees (30-40) along with some metrics associated with those employees, about 14 metrics each. I've done some tutorials online and can't quite get how I should proceed. What I have so far is below. It's not much, basically I think I can only add the employees to a dictionary in the class, but I don't know where to go from here.
class iagent
private di_agents
private ar_metrics
private pri_agent_counter
Public function add_agent(uuid)
di_agents.Add uuid, pri_agent_counter
pri_agent_counter=pri_agent_counter+1
end function
private sub Class_initialize
pri_agent_counter=1
dim ar_metrics(14, 5)
set di_agents = CreateObject("Scripting.Dictionary")
end sub
end class
The class you have is just a wrapper around a dictionary. Are you talking about creating a class that represents an employee?
Class Employee
Public Name
Public Age
Public Phone
'other properties
End Class
Then you can instantiate Employee like this and set your properties
Set e = New Employee
e.Name = "Some name"
You could then store your instances of Employee in a dictionary, perhaps paired with an ID:
Set d = CreateObject("Scripting.Dictionary")
Call d.Add(uuid, e)
However, you're better off using a database for this and using ASP/VBS to extract records... Unless this is just an exercise

Loading particular peoperties for entity and assigning it as reference to another entity

Example:
I am entering a new invoice. For this invoice I need to enter a customer. Lets assume that we retrieved a list of customers:
var list = Context.Set<Customer>().ToList();
Here I see two issues:
1) I do not need to bring all information for customer, I only need Id, Code and Name
2) Customer in current DbContext is read-only, so it would be nice if it is possible to tell DbContext not to monitor their states, to improve performance.
Questions:
1) Can we load only partial data for customer, but still be able to assign it to Invoice (see code bellow)?
2) Can we tell DbContext not to monitor Customers for changes, and still be able to do this:
Invoice.Customer = CustomerList[10];
There's not a direct way to do exactly what you want, but you might be able to achieve your goals with some compromise.
I do not need to bring all information for customer, I only need Id,
Code and Name
There isn't a way for EF to create a partially loaded entity, but you could create an anonymous type:
Context.Customers.Select(c => new {Id = c.CustomerId, Code = c.Code, Name = c.Name}).Tolist()
If you could live with the new anonymous type then use that, or you could then iterate through that list, creating actual customer objects.
Customer in current DbContext is read-only, so it would be nice if it
is possible to tell DbContext not to monitor their states, to improve
performance.
EF provides an Extension of AsNoTracking() which will do exactly what you're looking for:
var list = Context.Set<Customer>().AsNoTracking().ToList();
Depending on what you choose from above, the following code may change, but this code does achieve what you're looking for. Partially loads the customer, but still allows you to attach the customer to the invoice.
Note: You'll need to attach the customer to your context before you can use it, and then setting it to a state of Unchanged will prevent it from overwriting exiting data.
m = new Model();
var list = m.Customers.Select(c => new {Id = c.CustomerId, Code = c.Code, Name = c.Name});
List<Customer> customerList = new List<Customer>();
foreach (var item in list)
{
customerList.Add(new Customer()
{
CustomerId = item.Id,
Code = item.Code,
Name = item.Name
});
}
Invoice i = new Invoice();
var customer = customerList.First();
m.Customers.Attach(customer);
m.Entry(customer).State = EntityState.Unchanged;
i.Customer = customer;
m.Invoices.Add(i);
m.SaveChanges();