You are viewing a single comment's thread from:

RE: STANDARDIZED REFERENCES WITH REVIEWS ... [ Word count: 8.600 ~ 35 PAGES | Revised: 2018.11.7 ]

in #science5 years ago (edited)
To be part of a longer text posted later.

REASONING BY PASSING MESSAGES

DEVELOPMENT

 
A priority is to get message passing up and running. Then develop everything else, as resources permit. According to further priorities.

Then carefully test what is built. Afterwards continue making and adding features that interact with those tested and valid. Repeat. The system becomes more useful as more things get built and can be used to build things for the next version of it.

NOTATION.

 
Let <=| mean "if".

And then we have the following.

(A ,, B = B ,, A) <=| (A ≠ B)

(A , B ≠ B , A) <=| (A ≠ B)

DESIGN.

 
So a message to begin building around would be something like ( 5,, 3 | | | | ).

A minimal working method would be something very trivial like Multiply2.

The nice thing about the approach is that it is mostly atomic; how one thing is implemented does not affect the other things.

The basic unit is an actor. We can use the term agent when the basic actor is loaded up with sufficiently many methods or several actors rigidly interact producing a complex adaptive system equivalent to an actor loaded up with sufficiently many methods. There is a formal way to distinguish them, but more on that later.

And from simple units more complex units realizing various features can be built.

One major benefit is that, if the actor formulism is used, one can prove things about it, predict things before building.

Then decide how to distribute time building which interesting features accordingly.

For example, a neural network layer can be built from actors.

Each however has somewhat specialized methods --- there are some very interesting things one can do with such systems.

And then one can implement several methods by which one can be sure of statistical reliability and implementing exceptions and automating that process when different intelligent subsystems built in isolation with sufficient but minimal thought regarding combination are in fact combined. Fault tolerance is required because if there are too many different methods, most combinations are not merely not tested. They cannot be tested --- they are too many. Most will, most likely, never occur.

The basic unit. Similar to some concurrent prologs decades back.

( Inputs | Guards | Methods | Parameters | Outputs )

Message contents are typically inputs.

Some actors/agents are messages. The difference is relative. Not absolute.

All actors can operate on other actors. That is inherited.

In a pair, which one is a message, if any, decides the order of which one goes first.

The message always goes first.

Meanwhile the message is typically a very stripped down actor and terminates when the inputs are copied into the inputs field of the actor on which it operates.

So if M is the message sent to A, you have M(A), and only then, if nothing happens, does the system attempt A(M).

Otherwise both are the same type of object and inherit the same common attributes.

This can be implemented in many ways.

Lower level implementation is relatively open ended. It does not matter so much so long as relatively efficient.

Everything beyond that is built in terms of these units.

Some properties are significant.

Consider ( | | Method1,, Method2,, Method3 | | ).

( "Blue" | | | | ) "arrives".

There are no checks. So then ( "Blue" | | | | ) should operate on ( | | Method1,, Method2,, Method3 | | ) and copy "Blue" into ( | | Method1,, Method2,, Method3 | | ).

Which has the following result: ( "Blue" | | Method1,, Method2,, Method3 | | ).

And the message process terminates. It's gone.

If it failed to copy then ( | | Method1,, Method2,, Method3 | | ) would have tried, next, operating on ( "Blue" | | | | ).

However suppose ( "Blue" | | | | ) communicated its input.

We may later implement a check that it really communicated its input. But the system is generally fault tolerant. (This will be discussed later.)

An important attribute of actors here is that they can "randomly" select a method if several are available.

So then ( "Blue" | | Method1,, Method2,, Method3 | | ) will try Method2("Blue").

What does "try" mean in that context?

It will spawn another actor.

Can you guess the contents of that actor?

( "Blue" | | Method2 | SendMessage(Output).To(Source),, Temporary | )

Method2("Blue") will run, storing outputs, if any, in the last field of the actor.

We can use the Temporary parameter to remove the method instead of placing an exception in the parameters field. The actor is temporary. Like scratch paper.

Source grabs the name or address of the actor which spawned this one. Does this while spawning.

Two possible outcomes.

( | | | SendMessage(Output).To(Source),, Temporary | )

or

( | | | SendMessage(Output).To(Source),, Temporary | "Color" )

It sends off "Color" in a message it spawns.

Which leaves ( | | | SendMessage(Output).To(Source),, Temporary | )

Terminates.

Meanwhile the previous actor "logically" reduces to ( "Blue" | | Method1,, Method3 | | ).

What it actually becomes is something like ( "Blue" | | Method1,, Method2,, Method3 | Method2.Ignore(For("Blue")) | ).

If there are no methods and no outputs, an actor idles. Halts.
If there are no inputs and no outputs, it halts.
If there are no inputs or no methods and no outputs, it terminates.

There are some more details, but more on those later.

For test purposes, to begin, the above is a good place.

So the logic is basically that of a sophisticated guess and check.

If there are many methods loaded, a guard is some set of heuristics which automatically sets some Method___.Ignore(For("Blue")) parameters. Skips some methods.

Logically it just eliminates some methods from being run immediately.

We can ignore guards, they will be discussed later.

Another important point. Actors cannot arbitrarily operate on each other. They must be "sent" as messages. Which is what controls order, in a basically unordered environment.

Furthermore one actor cannot look much inside another actor. Only exception is copying to the memory allocated for inputs.

We can start by globally capping memory for each field.

Say about 256 KB each.

Basically the thing we want to be most careful about is memory.

Imagine each user as a hundred processes or two hundred processes. Like that.

Typically some rate control will be in place.

Actors do not communicate directly but through mailboxes.

Mailboxes have no methods other than one which deletes inputs if another actor operates on the mailbox, copies the input, and copies into the mailbox a "coinput".

The method only operates on matching input,coinput pairs and now it successfully deletes a triple consisting of an exception paramater, the input, and the coinput. For example.

Before there was only the input, the method runs, does nothing, and a parameter to ignore that input is produced.

Methods can be ordinary, small programs. Links to files on a server.

A goal is to make sure methods can be built in isolation and generically load them into actors as needed.

What the actor itself largely does is manage data and randomize which program it runs on the data from a list.

Messaging imposes general directions in the graph of such operations.

COMMENT

None of the above is to be confused with object oriented functionality already in most programming languages. Much of the basic science type AI literature ignores actual languages or development. For reasoning in terms used in that literature, different primitives need to be constructed.

What is desired here is to build generic components that can be further manipulated with a specific syntax. (Meanwhile excluding and locking down any other syntax.) For example, like the following.

DeclareActor:
       Name_TheNameWeWant,
       Inputs_{ ... },
       Guards_{ ... },
       Methods_{ ... },
       Parameters_{ ... },
       Outputs_{ ... };

( 5,,3 | | | | ).(Developer.Actor) |- Other.Actor

which means Actor "Developer" sends the message ( 5,,3 | | | | ). It sends it to Actor "Other".

It's a producer. Takes inputs in turn from the developer.

?Outputs(TheNameWeWant.Actor) = Outputs_{ ... }

5 and 3 are not states of any widely accessible variables. They are just data, givens, and only accessible to anybody in message form.

Methods can be names of files in the same directory. Smaller programs. Or code explicitly embedded in { .... }.

It should be possible for a program that takes inputs to consist entirely of a single actor declaration.

So that, for example, something like ( 5,,3 | | | | ).(Developer.Actor) |- (Load(FileLocation); Called: "Other.Actor") is also valid.

And once an initial message is sent and a process is begun many actors will automatically message other actors, until messages begin to return to Developer.Actor. Which displays them. So that interface is both source and sink, but at different times.

Object oriented is implemented and even formalized [ABA96], more often than not, such that A(B) means at the lowest level that even if B is just something like 0, in a sense B is what really asks a question to A, and not the other way around. The object A just parametrizes a lookup map operation for B. The map is either inherited or embedded in A. That map points to operations or functions declared earlier, depending on the input. (Hence why it can be said that objects are not strictly reasoned about as if functions. They point to functions.) Which object takes the input merely determines which lookup is used. Lookups can be updated. Suppose then A(B) points to M. Then the method M is invoked on input B. The result is an output, typically the state of a variable. And this is more or less accessible in the whole system. C(B) would parametrize the lookup differently, and a different lookup map, for B pointing to W would be processed, leading to the output being W(B).

Comparing this with various kinds of message passing there are some differences. (i) Objects have their own memory, and like in the case we consider store copies of input and outputs, or (ii) are pure logic like before, but in neither case are outputs ever locally or globally accessible. The outputs are locked down --- they have a recipient, and only that recipient, if anything, can access those values. Not reasonable about in terms of the states of accessible variables. Which can be implemented many ways. For example, ordinary variables with state locked down by checks with exceptions, all in many local instances. Next actors don't do direct lookup, but use random selection, heuristics, the guess and check approach of logical programming until all option or inputs or output are eliminated. Those are not straightforward lookup operations. And so on.

So even if it sometimes appears like it, message passing is not quite a special case of that general case, the ordinary functionality already in most languages. It requires a bit more. Which can be built more or less easily with most languages using that ordinary functionality.

Coin Marketplace

STEEM 0.33
TRX 0.11
JST 0.034
BTC 66438.74
ETH 3268.32
USDT 1.00
SBD 4.39