Skip to content

Commit

Permalink
22286: Amlg lang improvements: removes query_weighted_sample, weighte…
Browse files Browse the repository at this point in the history
…d_rand, updates rand, query_sample, sort, reduce, MAJOR (#327)

Removes query_weighted_sample and weighted_rand, updates query_sample
and rand to handle functionality.
Removes access to (target) from reduce and sort opcodes for performance
and consistency reasons.
Improves documentation and clarifies some opcode use.
  • Loading branch information
howsohazard authored Dec 17, 2024
1 parent e837c79 commit f797e18
Show file tree
Hide file tree
Showing 15 changed files with 486 additions and 909 deletions.
45 changes: 15 additions & 30 deletions docs/language.js

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/Amalgam/Opcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ void StringInternPool::InitializeStaticStrings()

//simulation and operations
EmplaceNodeTypeString(ENT_RAND, "rand");
EmplaceNodeTypeString(ENT_WEIGHTED_RAND, "weighted_rand");
EmplaceNodeTypeString(ENT_GET_RAND_SEED, "get_rand_seed");
EmplaceNodeTypeString(ENT_SET_RAND_SEED, "set_rand_seed");
EmplaceNodeTypeString(ENT_SYSTEM_TIME, "system_time");
Expand Down Expand Up @@ -257,7 +256,6 @@ void StringInternPool::InitializeStaticStrings()
EmplaceNodeTypeString(ENT_COMPUTE_ON_CONTAINED_ENTITIES, "compute_on_contained_entities");
EmplaceNodeTypeString(ENT_QUERY_SELECT, "query_select");
EmplaceNodeTypeString(ENT_QUERY_SAMPLE, "query_sample");
EmplaceNodeTypeString(ENT_QUERY_WEIGHTED_SAMPLE, "query_weighted_sample");
EmplaceNodeTypeString(ENT_QUERY_IN_ENTITY_LIST, "query_in_entity_list");
EmplaceNodeTypeString(ENT_QUERY_NOT_IN_ENTITY_LIST, "query_not_in_entity_list");
EmplaceNodeTypeString(ENT_QUERY_EXISTS, "query_exists");
Expand Down
8 changes: 3 additions & 5 deletions src/Amalgam/Opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ enum EvaluableNodeType : uint8_t

//simulation and operations
ENT_RAND,
ENT_WEIGHTED_RAND,
ENT_GET_RAND_SEED,
ENT_SET_RAND_SEED,
ENT_SYSTEM_TIME,
Expand Down Expand Up @@ -238,7 +237,6 @@ enum EvaluableNodeType : uint8_t
ENT_COMPUTE_ON_CONTAINED_ENTITIES,
ENT_QUERY_SELECT,
ENT_QUERY_SAMPLE,
ENT_QUERY_WEIGHTED_SAMPLE,
ENT_QUERY_IN_ENTITY_LIST,
ENT_QUERY_NOT_IN_ENTITY_LIST,
ENT_QUERY_EXISTS,
Expand Down Expand Up @@ -337,7 +335,7 @@ constexpr OrderedChildNodeType GetInstructionOrderedChildNodeType(EvaluableNodeT
case ENT_SET_ENTITY_RAND_SEED:
case ENT_CREATE_ENTITIES:
case ENT_CONTAINED_ENTITIES: case ENT_COMPUTE_ON_CONTAINED_ENTITIES:
case ENT_QUERY_SELECT: case ENT_QUERY_SAMPLE: case ENT_QUERY_WEIGHTED_SAMPLE:
case ENT_QUERY_SELECT: case ENT_QUERY_SAMPLE:
case ENT_QUERY_IN_ENTITY_LIST: case ENT_QUERY_NOT_IN_ENTITY_LIST:
case ENT_QUERY_EXISTS: case ENT_QUERY_NOT_EXISTS:
case ENT_QUERY_EQUALS: case ENT_QUERY_NOT_EQUALS:
Expand Down Expand Up @@ -375,7 +373,7 @@ constexpr OrderedChildNodeType GetInstructionOrderedChildNodeType(EvaluableNodeT
case ENT_GET:
case ENT_TARGET: case ENT_CURRENT_INDEX: case ENT_CURRENT_VALUE: case ENT_PREVIOUS_RESULT:
case ENT_OPCODE_STACK: case ENT_STACK: case ENT_ARGS:
case ENT_RAND: case ENT_WEIGHTED_RAND: case ENT_GET_RAND_SEED: case ENT_SET_RAND_SEED:
case ENT_RAND: case ENT_GET_RAND_SEED: case ENT_SET_RAND_SEED:
case ENT_SYSTEM_TIME:
case ENT_GET_DIGITS: case ENT_SET_DIGITS:
case ENT_FLOOR: case ENT_CEILING: case ENT_ROUND:
Expand Down Expand Up @@ -482,7 +480,7 @@ constexpr bool DoesEvaluableNodeTypeCreateScope(EvaluableNodeType t)
constexpr bool IsEvaluableNodeTypeQuery(EvaluableNodeType t)
{
return (t == ENT_QUERY_SELECT || t == ENT_QUERY_IN_ENTITY_LIST || t == ENT_QUERY_NOT_IN_ENTITY_LIST
|| t == ENT_QUERY_SAMPLE || t == ENT_QUERY_WEIGHTED_SAMPLE || t == ENT_QUERY_EXISTS || t == ENT_QUERY_NOT_EXISTS
|| t == ENT_QUERY_SAMPLE || t == ENT_QUERY_EXISTS || t == ENT_QUERY_NOT_EXISTS
|| t == ENT_QUERY_EQUALS || t == ENT_QUERY_NOT_EQUALS
|| t == ENT_QUERY_BETWEEN || t == ENT_QUERY_NOT_BETWEEN || t == ENT_QUERY_AMONG || t == ENT_QUERY_NOT_AMONG
|| t == ENT_QUERY_MAX || t == ENT_QUERY_MIN || t == ENT_QUERY_SUM || t == ENT_QUERY_MODE
Expand Down
37 changes: 14 additions & 23 deletions src/Amalgam/amlg_code/full_test.amlg
Original file line number Diff line number Diff line change
Expand Up @@ -1163,26 +1163,17 @@

(print (rand 50 4) "\n")

(print "--weighted_rand--\n")
(print (weighted_rand (associate "a" .25 "b" .75)) "\n")
(print (weighted_rand (associate "a" .25 "b" .75) 4) "\n")
(print (rand (associate "a" .25 "b" .75)) "\n")
(print (rand (associate "a" .25 "b" .75) 16) "\n")

(print (weighted_rand (list (list "a" "b") (list .25 .75)) ) "\n")
(print (weighted_rand (list (list "a" "b") (list .25 .75)) 4) "\n")
(print (weighted_rand (list (list "a" "b") (list 0 0)) 4 ) "\n" )

(print "infinity test c or d: " (weighted_rand (associate "a" .25 "b" .75 "c" .infinity "d" .infinity) 4) "\n")
(print "infinity test c or d: " (weighted_rand (list (list "a" "b" "c" "d") (list .25 .75 .infinity .infinity)) 4) "\n")
(print "infinity test c or d: " (rand (associate "a" .25 "b" .75 "c" .infinity "d" .infinity) 4) "\n")

;these should come out somewhere near the correct proportions
(print (zip (lambda (+ (current_value 1) (current_value))) (weighted_rand (associate "a" .25 "b" .5 "c" .25) 100) 1) "\n")

;these should come out somewhere near the correct proportions
(print (zip (lambda (+ (current_value 1) (current_value))) (weighted_rand (list (list "a" "b" "c") (list .25 .5 .25)) 100) 1) "\n")
(print (zip (lambda (+ (current_value 1) (current_value))) (rand (associate "a" .25 "b" .5 "c" .25) 100) 1) "\n")

;these should be weighted toward smaller numbers
(print
(weighted_rand
(rand
(zip
(range 1 10)
(map (lambda
Expand Down Expand Up @@ -2519,38 +2510,38 @@


(print (contained_entities "TestContainerExec" (list
(query_sample 1 (rand) )
(query_sample 1 (null) (rand) )
)))

(print (contained_entities "TestContainerExec" (list
(query_sample 1 (null) )
(query_sample 1 (null) (null) )
)))

(print "--query_weighted_sample--\n")
(print "with weights\n")

(print (contained_entities "TestContainerExec" (list
(query_weighted_sample "weight")
(query_sample 1 "weight")
)))

(print (contained_entities "TestContainerExec" (list
(query_weighted_sample "weight")
(query_sample 1 "weight")
)))

(print (contained_entities "TestContainerExec" (list
(query_weighted_sample "weight" 20 (rand) )
(query_sample 20 "weight" (rand) )
)))

(print (contained_entities "TestContainerExec" (list
(query_weighted_sample "weight" 20 (null) )
(query_sample 20 "weight" (null) )
)))

(print (contained_entities "TestContainerExec" (list
(query_not_in_entity_list (list "Child1"))
(query_weighted_sample "weight" 10 (rand) )
(query_sample 10 "weight" (rand) )
)))

(print (contained_entities "TestContainerExec" (list
(query_weighted_sample "weight" 10 (rand) )
(query_sample 10 "weight" (rand) )
(query_not_in_entity_list (list "Child1"))
)))

Expand Down
92 changes: 79 additions & 13 deletions src/Amalgam/amlg_code/test.amlg
Original file line number Diff line number Diff line change
@@ -1,14 +1,80 @@
(seq
(create_entities "persist_transactions" (list 1 2 3 4))
(create_entities (list "persist_transactions" "child") (list 5 6 7))
(create_entities (list "persist_transactions" "child" "doublechild1") (lambda (list ##eight 8 ##nine 9)))
(create_entities (list "persist_transactions" "child" "doublechild3") (list 12 13))
(store_entity "amlg_code/test_output/persist_transactions.caml" "persist_transactions" (null) (true) {flatten (true) transactional (true)})
(create_entities (list "persist_transactions" "child" "doublechild2") (list 10 11))
(destroy_entities (list "persist_transactions" "child" "doublechild3"))
(assign_to_entities (list "persist_transactions" "child" "doublechild1") {eight 88})

(load_entity "amlg_code/test_output/persist_transactions.caml" "persist_transactions_copy" (null) (false) {execute_on_load (true) transactional (true) require_version_compatibility (true)})
(print (difference_entities "persist_transactions_copy" "persist_transactions") "\n")
(destroy_entities "persist_transactions_copy" "persist_transactions")
)


(create_entities "TestContainerExec"
(lambda (parallel
##^a 3
##b (contained_entities)
##c (+ x 1)
##d (call_entity "Child5" "q" (assoc x x))
##!e 12
##x 4
##y 5
))
)
(create_entities (list "TestContainerExec" "Child1")
(lambda (parallel
##x 3
##y 4
##!e 7
##weight 0.45
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child2")
(lambda (parallel
##x -1
##y -1
##weight 0.45
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child3")
(lambda (parallel
##x 100
##y 100
##weight 0.02
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child4")
(lambda (parallel
##x 100
##y 100
##radius 400
##weight 0.02
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child5")
(lambda (parallel
##p 3
##q (+ x (call_container "^a"))
##bar "crunchy"
##weight 0.02
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child6")
(lambda (parallel
##x 1
##y 2
##bar "not crunchy"
##weight 0.02
##weight_eq 1
))
)
(create_entities (list "TestContainerExec" "Child7")
(lambda (parallel
##x 0
##y 10
##weight 0.02
##weight_eq 1
))
)

(print (contained_entities "TestContainerExec" (list
(query_sample 1 "weight")
)))

)
98 changes: 37 additions & 61 deletions src/Amalgam/entity/EntityQueries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ bool EntityQueryCondition::DoesEntityMatchCondition(Entity *e)

case ENT_QUERY_SELECT:
case ENT_QUERY_SAMPLE:
case ENT_QUERY_WEIGHTED_SAMPLE:
//it does not fail the condition here - needs to be checked elsewhere
return true;

Expand Down Expand Up @@ -352,75 +351,52 @@ EvaluableNodeReference EntityQueryCondition::GetMatchingEntities(Entity *contain
else //just use a random seed
random_stream.SetState("12345");

//select num_to_select entities and save them in the sample vector
for(size_t i = 0; i < num_to_sample; i++)
if(singleLabel == StringInternPool::NOT_A_STRING_ID)
{
size_t index_to_swap = randomStream.RandSize(num_entities);
Entity *selected = matching_entities[index_to_swap];
samples.emplace_back(selected);
//select num_to_select entities and save them in the sample vector
for(size_t i = 0; i < num_to_sample; i++)
{
size_t index_to_swap = randomStream.RandSize(num_entities);
Entity *selected = matching_entities[index_to_swap];
samples.emplace_back(selected);
}
}

//swap samples vector with the matching_entities
std::swap(matching_entities, samples);
return EvaluableNodeReference::Null();
}

case ENT_QUERY_WEIGHTED_SAMPLE:
{
size_t num_entities = matching_entities.size();
size_t num_to_sample = static_cast<size_t>(maxToRetrieve);
auto weight_label_id = singleLabel;

if(num_entities == 0 || num_to_sample == 0)
else //weighted
{
matching_entities.clear();
return EvaluableNodeReference::Null();
}

//retrieve weights
std::vector<double> entity_weights;
entity_weights.reserve(num_to_sample);
//retrieve weights
std::vector<double> entity_weights;
entity_weights.reserve(num_to_sample);

//retrieve and accumulate weights
for(size_t i = 0; i < matching_entities.size(); i++)
{
double value;
Entity *e = matching_entities[i];
if(e != nullptr && e->GetValueAtLabelAsNumber(weight_label_id, value))
//retrieve and accumulate weights
for(Entity *e : matching_entities)
{
if(FastIsNaN(value))
value = 0.0;
double value;
if(e != nullptr && e->GetValueAtLabelAsNumber(singleLabel, value))
{
if(FastIsNaN(value))
value = 0.0;

entity_weights.push_back(value);
entity_weights.push_back(value);
}
else
{
entity_weights.push_back(0.0);
}
}
else

//if just one sample, brute-force it
if(num_to_sample == 1)
{
entity_weights.push_back(0.0);
size_t selected_index = WeightedDiscreteRandomSample(entity_weights, random_stream, true);
Entity *selected = matching_entities[selected_index];
samples.emplace_back(selected);
}
else //build temporary cache and query
{
WeightedDiscreteRandomStreamTransform<Entity *> wdrst(matching_entities, entity_weights, true);
for(size_t i = 0; i < num_to_sample; i++)
samples.emplace_back(wdrst.WeightedDiscreteRand(random_stream));
}
}

//obtain random stream either from the condition or use a default one
RandomStream random_stream;
if(hasRandomStream)
random_stream = randomStream.CreateOtherStreamViaRand();
else //just use a random seed
random_stream.SetState("12345");

std::vector<Entity *> samples;
samples.reserve(num_to_sample);

//if just one sample, brute-force it
if(num_to_sample == 1)
{
size_t selected_index = WeightedDiscreteRandomSample(entity_weights, random_stream, true);
Entity *selected = matching_entities[selected_index];
samples.emplace_back(selected);
}
else //build temporary cache and query
{
WeightedDiscreteRandomStreamTransform<Entity *> wdrst(matching_entities, entity_weights, true);
for(size_t i = 0; i < num_to_sample; i++)
samples.emplace_back(wdrst.WeightedDiscreteRand(random_stream));
}

//swap samples vector with the matching_entities
Expand Down
21 changes: 6 additions & 15 deletions src/Amalgam/entity/EntityQueryBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,12 +652,12 @@ namespace EntityQueryBuilder
{
case ENT_QUERY_SELECT:
{
cur_condition->maxToRetrieve = (ocn.size() >= 1) ? EvaluableNode::ToNumber(ocn[0], 0.0) : 0;
cur_condition->maxToRetrieve = (ocn.size() > 0) ? EvaluableNode::ToNumber(ocn[0], 0.0) : 0;

cur_condition->hasStartOffset = (ocn.size() >= 2);
cur_condition->hasStartOffset = (ocn.size() > 1);
cur_condition->startOffset = cur_condition->hasStartOffset ? static_cast<size_t>(EvaluableNode::ToNumber(ocn[1], 0.0)) : 0;

cur_condition->hasRandomStream = (ocn.size() >= 3 && !EvaluableNode::IsNull(ocn[2]));
cur_condition->hasRandomStream = (ocn.size() > 2 && !EvaluableNode::IsNull(ocn[2]));
if(cur_condition->hasRandomStream)
cur_condition->randomStream.SetState(EvaluableNode::ToString(ocn[2]));
else
Expand All @@ -668,23 +668,14 @@ namespace EntityQueryBuilder
case ENT_QUERY_SAMPLE:
{
cur_condition->maxToRetrieve = (ocn.size() > 0) ? EvaluableNode::ToNumber(ocn[0], 0.0) : 1;
cur_condition->hasRandomStream = (ocn.size() > 1 && !EvaluableNode::IsNull(ocn[1]));
if(cur_condition->hasRandomStream)
cur_condition->randomStream.SetState(EvaluableNode::ToString(ocn[1]));
else
cur_condition->randomStream = rs.CreateOtherStreamViaRand();
break;
}
case ENT_QUERY_WEIGHTED_SAMPLE:
{
cur_condition->singleLabel = (ocn.size() > 0) ? EvaluableNode::ToStringIDIfExists(ocn[0]) : StringInternPool::NOT_A_STRING_ID;
cur_condition->maxToRetrieve = (ocn.size() > 1) ? EvaluableNode::ToNumber(ocn[1], 0.0) : 1;
cur_condition->singleLabel = (ocn.size() > 1) ? EvaluableNode::ToStringIDIfExists(ocn[1]) : StringInternPool::NOT_A_STRING_ID;

cur_condition->hasRandomStream = (ocn.size() > 2 && !EvaluableNode::IsNull(ocn[2]));
if(cur_condition->hasRandomStream)
cur_condition->randomStream.SetState(EvaluableNode::ToString(ocn[2]));
else
cur_condition->randomStream = rs.CreateOtherStreamViaRand();
break;
break;
}
case ENT_QUERY_IN_ENTITY_LIST:
case ENT_QUERY_NOT_IN_ENTITY_LIST:
Expand Down
Loading

0 comments on commit f797e18

Please sign in to comment.