Commit e24ac41f authored by danfis's avatar danfis

Module for computation of redundant sets.

parent f800748b
......@@ -25,6 +25,7 @@ OBJS += mutex_pair
OBJS += mgroup
OBJS += op_mutex_pair
OBJS += op_mutex_infer
OBJS += op_mutex_sym_redundant
OBJS += op_mgroup
OBJS += h1
OBJS += h2
......
......@@ -25,9 +25,9 @@
#include "plan/strips_reduce.h"
#include "plan/sym.h"
#include "plan/famgroup.h"
#include "plan/op_mgroup.h"
#include "plan/op_mutex_pair.h"
#include "plan/op_mutex_infer.h"
#include "plan/op_mutex_sym_redundant.h"
static struct {
const char *domain_pddl;
......@@ -38,7 +38,7 @@ static struct {
NULL, /* domain_pddl */
NULL, /* problem_pddl */
-1, /* max_mem */
1800, /* max_time: 30 min */
18000, /* max_time: 300 min */
};
static pthread_t th_time_watchdog;
......@@ -181,36 +181,40 @@ static int reduce(plan_strips_t *strips,
return 0;
}
static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
static void computeSymmetry(const plan_strips_t *strips,
plan_sym_t *sym,
bor_iset_t *sym_ops,
bor_err_t *err)
{
plan_sym_t sym;
plan_mutex_pairs_t mutex;
BOR_ISET(sym_ops);
if (reduce(strips, &mutex, err) != 0)
BOR_TRACE_RET(err, -1);
BOR_INFO2(err, "Computing symmetries:");
planSymInitPDG(&sym, strips);
BOR_INFO(err, " --> symmetry generators: %d", sym.gen_size);
planSymInitPDG(sym, strips);
BOR_INFO(err, " --> symmetry generators: %d", sym->gen_size);
//planSymPrintDebug(&sym, stdout);
for (int i = 0; i < sym.gen_size; ++i){
const plan_sym_gen_t *gen = sym.gen + i;
for (int i = 0; i < sym->gen_size; ++i){
const plan_sym_gen_t *gen = sym->gen + i;
for (int j = 0; j < gen->op_cycle_size; ++j)
borISetUnion(&sym_ops, &gen->op_cycle[j]);
borISetUnion(sym_ops, &gen->op_cycle[j]);
}
BOR_INFO(err, " --> non-identity symmetry operators: %d",
borISetSize(&sym_ops));
borISetSize(sym_ops));
}
static int inferOpMutexes(const plan_strips_t *strips,
const plan_mutex_pairs_t *mutex,
const plan_sym_t *sym,
plan_op_mutex_pairs_t *op_mutex,
bor_err_t *err)
{
plan_mgroups_t mgroup;
planMGroupsInit(&mgroup);
BOR_INFO2(err, "Inference of fam-groups:");
if (planFAMGroupsInferMaximal(&mgroup, strips) != 0)
unsigned fam_flags = PLAN_FAMGROUP_MAXIMAL;
//fam_flags |= PLAN_FAMGROUP_KEEP_ONLY_ASYMETRIC;
//if (planFAMGroupsInferMaximal(&mgroup, strips) != 0)
if (planFAMGroupsInferSym(&mgroup, strips, sym, fam_flags) != 0)
BOR_ERR_RET2(err, -1, "Error while inferring fam-groups.");
BOR_INFO(err, " --> Found %d fam-groups", mgroup.mgroup_size);
plan_op_mutex_pairs_t op_mutex;
plan_op_mutex_pairs_t op_mutex_fam;
plan_op_mutex_pairs_t op_mutex_h2_comp;
plan_op_mutex_pairs_t op_mutex_h2_all;
......@@ -224,22 +228,20 @@ static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
planOpMutexInferH2OpFactCompilation(&op_mutex_h2_comp, strips, err);
planOpMutexPairsInit(&op_mutex_h2_all, strips);
planOpMutexInferH2FromEachOp(&op_mutex_h2_all, strips, &mutex,
&sym_ops, err);
//planOpMutexInferH2FromEachOp(&op_mutex_h2_all, strips, mutex, NULL, err);
planOpMutexPairsInit(&op_mutex_uncover, strips);
planOpMutexInferUncoveredFacts(&op_mutex_uncover, strips, &mgroup, err);
planOpMutexPairsInit(&op_mutex, strips);
planOpMutexPairsUnion(&op_mutex, &op_mutex_fam);
planOpMutexPairsUnion(&op_mutex, &op_mutex_h2_comp);
planOpMutexPairsUnion(&op_mutex, &op_mutex_h2_all);
planOpMutexPairsUnion(&op_mutex, &op_mutex_uncover);
BOR_INFO(err, "Op-mutexes: %d", planOpMutexPairsSize(&op_mutex));
planOpMutexPairsUnion(op_mutex, &op_mutex_fam);
planOpMutexPairsUnion(op_mutex, &op_mutex_h2_comp);
planOpMutexPairsUnion(op_mutex, &op_mutex_h2_all);
planOpMutexPairsUnion(op_mutex, &op_mutex_uncover);
BOR_INFO(err, "Op-mutexes: %d", planOpMutexPairsSize(op_mutex));
int op_mutex_sym = 0;
for (int i = 0; i < sym.gen_size; ++i){
const plan_sym_gen_t *gen = sym.gen + i;
for (int i = 0; i < sym->gen_size; ++i){
const plan_sym_gen_t *gen = sym->gen + i;
for (int j = 0; j < gen->op_cycle_size; ++j){
const bor_iset_t *cycle = &gen->op_cycle[j];
int size = borISetSize(cycle);
......@@ -247,7 +249,7 @@ static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
int o1 = borISetGet(cycle, k);
for (int l = k + 1; l < size; ++l){
int o2 = borISetGet(cycle, l);
if (planOpMutexPairsIsMutex(&op_mutex, o1, o2))
if (planOpMutexPairsIsMutex(op_mutex, o1, o2))
++op_mutex_sym;
}
}
......@@ -258,13 +260,6 @@ static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
planOpMutexPairsInitCopy(&op_mutex_diff, &op_mutex_fam);
planOpMutexPairsMinus(&op_mutex_diff, &op_mutex_h2_comp);
BOR_INFO(err, "fam - h2-comp: %d", planOpMutexPairsSize(&op_mutex_diff));
/*
int o1, o2;
PLAN_OP_MUTEX_PAIRS_FOR_EACH_SORTED(&op_mutex_diff, o1, o2){
fprintf(stderr, "%d %d | %s | %s\n", o1, o2,
strips->op.op[o1].name, strips->op.op[o2].name);
}
*/
planOpMutexPairsFree(&op_mutex_diff);
planOpMutexPairsInitCopy(&op_mutex_diff, &op_mutex_fam);
......@@ -280,15 +275,6 @@ static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
planOpMutexPairsInitCopy(&op_mutex_diff, &op_mutex_h2_comp);
planOpMutexPairsMinus(&op_mutex_diff, &op_mutex_fam);
BOR_INFO(err, "h2-comp - fam: %d", planOpMutexPairsSize(&op_mutex_diff));
/*
{
int o1, o2;
PLAN_OP_MUTEX_PAIRS_FOR_EACH_SORTED(&op_mutex_diff, o1, o2){
fprintf(stderr, "%d %d | %s | %s\n", o1, o2,
strips->op.op[o1].name, strips->op.op[o2].name);
}
}
*/
planOpMutexPairsFree(&op_mutex_diff);
planOpMutexPairsInitCopy(&op_mutex_diff, &op_mutex_h2_comp);
......@@ -334,11 +320,62 @@ static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
planOpMutexPairsFree(&op_mutex_h2_comp);
planOpMutexPairsFree(&op_mutex_h2_all);
planOpMutexPairsFree(&op_mutex_uncover);
planOpMutexPairsFree(&op_mutex);
planMGroupsFree(&mgroup);
return 0;
}
static int reduceOpMutexSym(plan_strips_t *strips,
plan_mutex_pairs_t *mutex_pairs,
bor_err_t *err)
{
int change = 0;
plan_sym_t sym;
BOR_ISET(sym_ops);
computeSymmetry(strips, &sym, &sym_ops, err);
plan_op_mutex_pairs_t op_mutex;
planOpMutexPairsInit(&op_mutex, strips);
if (inferOpMutexes(strips, mutex_pairs, &sym, &op_mutex, err) != 0)
BOR_TRACE_RET(err, -1);
BOR_ISET(redundant);
planOpMutexSymRedundantFixpoint(&redundant, strips, &sym, &op_mutex, err);
if (borISetSize(&redundant) > 0)
change = 1;
planStripsDisableOps(strips, &redundant);
planStripsReduce(strips);
borISetFree(&redundant);
BOR_INFO(err, "Reduced with op-mutexes and symmetries. facts: %d, ops: %d",
planStripsFactsSize(&strips->fact),
planStripsOpsSize(&strips->op));
planOpMutexPairsFree(&op_mutex);
borISetFree(&sym_ops);
planSymFree(&sym);
planMGroupsFree(&mgroup);
return change;
}
static int sym_reduce(plan_strips_t *strips, bor_err_t *err)
{
plan_mutex_pairs_t mutex;
if (reduce(strips, &mutex, err) != 0)
BOR_TRACE_RET(err, -1);
int ret = 1;
while (ret == 1){
if ((ret = reduceOpMutexSym(strips, &mutex, err)) < 0)
BOR_TRACE_RET(err, -1);
}
if (reduce(strips, &mutex, err) != 0)
BOR_TRACE_RET(err, -1);
planMutexPairsFree(&mutex);
return 0;
......
/***
* cplan
* -------
* Copyright (c)2018 Daniel Fiser <[email protected]>,
* Faculty of Electrical Engineering, Czech Technical University in Prague.
* All rights reserved.
*
* This file is part of cplan.
*
* Distributed under the OSI-approved BSD License (the "License");
* see accompanying file BDS-LICENSE for details or see
* <http://www.opensource.org/licenses/bsd-license.php>.
*
* This software is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the License for more information.
*/
#ifndef __PLAN_OP_MUTEX_SYM_REDUNDANT_H__
#define __PLAN_OP_MUTEX_SYM_REDUNDANT_H__
#include <boruvka/err.h>
#include <plan/op_mutex_pair.h>
#include <plan/sym.h>
#include <plan/strips.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* Computes a set of redundant operators using fixpoint computation with a
* set of operator mutexes and symmetries.
*/
void planOpMutexSymRedundantFixpoint(bor_iset_t *redundant,
const plan_strips_t *strips,
const plan_sym_t *sym,
const plan_op_mutex_pairs_t *op_mutex,
bor_err_t *err);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* __PLAN_OP_MUTEX_SYM_REDUNDANT_H__ */
/***
* cplan
* -------
* Copyright (c)2018 Daniel Fiser <[email protected]>,
* Faculty of Electrical Engineering, Czech Technical University in Prague.
* All rights reserved.
*
* This file is part of cplan.
*
* Distributed under the OSI-approved BSD License (the "License");
* see accompanying file BDS-LICENSE for details or see
* <http://www.opensource.org/licenses/bsd-license.php>.
*
* This software is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the License for more information.
*/
#include <boruvka/alloc.h>
#include "plan/op_mutex_sym_redundant.h"
#include "assert.h"
struct reduce_gen_op {
int op_id;
int irrelevant;
bor_iset_t mutex_with;
};
typedef struct reduce_gen_op reduce_gen_op_t;
struct reduce_gen {
int gen_id;
int is_destroyed;
const plan_sym_gen_t *gen;
bor_iset_t relevant_op;
reduce_gen_op_t *op;
int op_size;
bor_iset_t redundant_set;
bor_iset_t destroyed_syms;
};
typedef struct reduce_gen reduce_gen_t;
struct reduce {
reduce_gen_t *gen;
int gen_size;
bor_iset_t pruned_ops;
};
typedef struct reduce reduce_t;
static void reduceGenInit(reduce_gen_t *rgen,
int gen_id,
const plan_sym_gen_t *gen,
const plan_sym_t *sym,
const plan_strips_t *strips,
const plan_op_mutex_pairs_t *op_mutex)
{
bzero(rgen, sizeof(*rgen));
rgen->gen_id = gen_id;
rgen->gen = gen;
const plan_strips_op_t *op;
PLAN_STRIPS_OPS_FOR_EACH(&strips->op, op){
if (gen->op[op->id] != op->id
&& planOpMutexPairsIsMutex(op_mutex, op->id, gen->op[op->id]))
borISetAdd(&rgen->relevant_op, op->id);
}
rgen->op_size = planStripsOpsSize(&strips->op);
rgen->op = BOR_CALLOC_ARR(reduce_gen_op_t, rgen->op_size);
for (int i = 0; i < rgen->op_size; ++i){
rgen->op[i].op_id = i;
rgen->op[i].irrelevant = 1;
}
int op_id;
BOR_ISET_FOR_EACH(&rgen->relevant_op, op_id){
reduce_gen_op_t *rop = rgen->op + op_id;
rop->irrelevant = 0;
planOpMutexPairsMutexWith(op_mutex, op_id, &rop->mutex_with);
borISetIntersect(&rop->mutex_with, &rgen->relevant_op);
}
}
static void reduceGenFree(reduce_gen_t *rgen)
{
borISetFree(&rgen->relevant_op);
for (int i = 0; i < rgen->op_size; ++i){
borISetFree(&rgen->op[i].mutex_with);
}
if (rgen->op != NULL)
BOR_FREE(rgen->op);
}
static void reduceInit(reduce_t *red,
const plan_strips_t *strips,
const plan_sym_t *sym,
const plan_op_mutex_pairs_t *op_mutex)
{
bzero(red, sizeof(*red));
red->gen_size = sym->gen_size;
red->gen = BOR_CALLOC_ARR(reduce_gen_t, sym->gen_size);
for (int i = 0; i < sym->gen_size; ++i)
reduceGenInit(red->gen + i, i, sym->gen + i, sym, strips, op_mutex);
}
static void reduceFree(reduce_t *red)
{
for (int i = 0; i < red->gen_size; ++i)
reduceGenFree(red->gen + i);
if (red->gen != NULL)
BOR_FREE(red->gen);
}
static int isDestroyed(const reduce_gen_t *rgen, const bor_iset_t *pruned_ops)
{
int op;
BOR_ISET_FOR_EACH(pruned_ops, op){
if (!borISetIn(rgen->gen->op[op], pruned_ops))
return 1;
}
return 0;
}
static void destroyedSymmetries(reduce_gen_t *rgen,
const reduce_t *red,
int prune_op)
{
borISetEmpty(&rgen->destroyed_syms);
for (int gi = 0; gi < red->gen_size; ++gi){
const plan_sym_gen_t *gen = red->gen[gi].gen;
int op;
if (prune_op >= 0
&& gen->op[prune_op] != prune_op
&& !borISetIn(gen->op[prune_op], &rgen->redundant_set)
&& !borISetIn(gen->op[prune_op], &red->pruned_ops)){
borISetAdd(&rgen->destroyed_syms, gi);
continue;
}
int cont = 0;
BOR_ISET_FOR_EACH(&rgen->redundant_set, op){
if (gen->op[op] != prune_op
&& !borISetIn(gen->op[op], &rgen->redundant_set)
&& !borISetIn(gen->op[op], &red->pruned_ops)){
borISetAdd(&rgen->destroyed_syms, gi);
cont = 1;
break;
}
}
if (cont)
continue;
BOR_ISET_FOR_EACH(&red->pruned_ops, op){
if (gen->op[op] != prune_op
&& !borISetIn(gen->op[op], &rgen->redundant_set)
&& !borISetIn(gen->op[op], &red->pruned_ops)){
borISetAdd(&rgen->destroyed_syms, gi);
break;
}
}
}
}
static int selectCandidate(reduce_gen_t *rgen,
const reduce_t *red,
const bor_iset_t *cand)
{
int sel = -1;
int destroy = INT_MAX;
int size = 0;
int op;
BOR_ISET_FOR_EACH(cand, op){
destroyedSymmetries(rgen, red, op);
int dest = borISetSize(&rgen->destroyed_syms);
int siz = borISetSize(&rgen->op[op].mutex_with);
if (dest < destroy || (dest == destroy && siz > size)){
//if (siz > size){
sel = op;
destroy = dest;
size = siz;
}
}
return sel;
}
static void findRedundantSet(reduce_gen_t *rgen, const reduce_t *red)
{
BOR_ISET(cand);
borISetEmpty(&rgen->redundant_set);
borISetUnion(&cand, &rgen->relevant_op);
while (borISetSize(&cand) > 0){
int prune_op = selectCandidate(rgen, red, &cand);
int keep_op = rgen->gen->op[prune_op];
borISetAdd(&rgen->redundant_set, prune_op);
borISetRm(&cand, prune_op);
borISetIntersect(&cand, &rgen->op[keep_op].mutex_with);
}
destroyedSymmetries(rgen, red, -1);
borISetFree(&cand);
}
static void pruneRedundantSet(reduce_t *red, const bor_iset_t *redundant)
{
borISetUnion(&red->pruned_ops, redundant);
for (int gi = 0; gi < red->gen_size; ++gi){
reduce_gen_t *rgen = red->gen + gi;
borISetMinus(&rgen->relevant_op, redundant);
for (int oi = 0; oi < rgen->op_size; ++oi)
borISetMinus(&rgen->op[oi].mutex_with, redundant);
rgen->is_destroyed = isDestroyed(rgen, &red->pruned_ops);
destroyedSymmetries(rgen, red, -1);
}
}
static void computeRedundantSets(reduce_t *red, bor_err_t *err)
{
BOR_INFO2(err, " --> Computing redundant sets for each symmetry");
for (int gi = 0; gi < red->gen_size; ++gi){
reduce_gen_t *rgen = red->gen + gi;
if (rgen->is_destroyed){
borISetEmpty(&rgen->redundant_set);
borISetEmpty(&rgen->destroyed_syms);
continue;
}
findRedundantSet(rgen, red);
BOR_INFO(err, " --> Sym %d: size: %d, destroyed symmetries: %d",
gi, borISetSize(&rgen->redundant_set),
borISetSize(&rgen->destroyed_syms));
}
}
static int selectRedundantSet(const reduce_t *red, bor_err_t *err)
{
int best_size = -1;
int best_sym_destroyed = INT_MAX;
int best = -1;
for (int gi = 0; gi < red->gen_size; ++gi){
const reduce_gen_t *rgen = red->gen + gi;
if (rgen->is_destroyed)
continue;
if (borISetSize(&rgen->redundant_set) == 0)
continue;
// TODO
//if (!borISetIsDisjunct(&rgen->redundant_set, &red->pruned_ops))
// continue;
int size = borISetSize(&rgen->redundant_set);
int destr = borISetSize(&rgen->destroyed_syms);
if (destr < best_sym_destroyed
|| (destr == best_sym_destroyed && size > best_size)){
//if (size > best_size){
best_size = size;
best_sym_destroyed = destr;
best = gi;
}
}
return best;
}
void planOpMutexSymRedundantFixpoint(bor_iset_t *redundant_out,
const plan_strips_t *strips,
const plan_sym_t *sym,
const plan_op_mutex_pairs_t *op_mutex,
bor_err_t *err)
{
reduce_t red;
int change, gen_id;
BOR_INFO2(err, "Redundant set with op-mutexes and symmetries:");
reduceInit(&red, strips, sym, op_mutex);
BOR_INFO2(err, " --> Initialized");
change = 1;
while (change){
change = 0;
computeRedundantSets(&red, err);
int local_change = 1;
// TODO
for (int i = 0; local_change && i < 10; ++i){
//while (change){
if ((gen_id = selectRedundantSet(&red, err)) >= 0){
// TODO
/*
if (!borISetIsDisjunct(&red.gen[gen_id].redundant_set,
&red.pruned_ops)){
break;
}
*/
BOR_INFO(err, " --> Selected redundant set from symmetry"
" %d with size %d destroying %d symmetries",
gen_id,
borISetSize(&red.gen[gen_id].redundant_set),
borISetSize(&red.gen[gen_id].destroyed_syms));
pruneRedundantSet(&red, &red.gen[gen_id].redundant_set);
change = local_change = 1;
BOR_INFO(err, " --> Redundant operators overall: %d",
borISetSize(&red.pruned_ops));
}
}
}
BOR_INFO(err, "Op-mutex symmetry redundant operators: %d",
borISetSize(&red.pruned_ops));
borISetUnion(redundant_out, &red.pruned_ops);
reduceFree(&red);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment